blob: 7614ed2b60b8def911d8095a8582696995d635ae [file] [log] [blame]
Brian3afd6fc2014-04-02 20:41:49 -07001#ifndef AOS_COMMON_UTIL_PHASED_LOOP_H_
2#define AOS_COMMON_UTIL_PHASED_LOOP_H_
brians343bc112013-02-10 01:53:46 +00003
Brian Silvermandcaa3f72015-11-29 05:32:08 +00004#include "aos/common/time.h"
5
6#include "aos/common/logging/logging.h"
brians343bc112013-02-10 01:53:46 +00007
8namespace aos {
9namespace time {
10
11// Will not be accurate if ms isn't a factor of 1000.
12// offset is in us.
Brian Silvermandcaa3f72015-11-29 05:32:08 +000013// DEPRECATED(Brian): Use PhasedLoop instead.
brians343bc112013-02-10 01:53:46 +000014void PhasedLoopXMS(int ms, int offset);
brians343bc112013-02-10 01:53:46 +000015
Brian Silvermandcaa3f72015-11-29 05:32:08 +000016// Handles sleeping until a fixed offset from some time interval.
17class PhasedLoop {
18 public:
19 // For example, with interval = 1s and offset = 0.1s this will fire at:
20 // 0.1s
21 // 1.1s
22 // ...
23 // 10000.1s
24 // offset must be >= Time::kZero and < interval.
Austin Schuh8aec1ed2016-05-01 13:29:20 -070025 PhasedLoop(
26 const monotonic_clock::duration interval,
27 const monotonic_clock::duration offset = monotonic_clock::duration(0))
Brian Silvermandcaa3f72015-11-29 05:32:08 +000028 : interval_(interval), offset_(offset), last_time_(offset) {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070029 CHECK_GE(offset, monotonic_clock::duration(0));
30 CHECK_GT(interval, monotonic_clock::duration(0));
Brian Silvermandcaa3f72015-11-29 05:32:08 +000031 CHECK_LT(offset, interval);
32 Reset();
33 }
34
35 // Resets the count of skipped iterations.
Austin Schuh8aec1ed2016-05-01 13:29:20 -070036 // Iterate(monotonic_now) will return 1 and set sleep_time() to something
37 // within interval of monotonic_now.
38 void Reset(const monotonic_clock::time_point monotonic_now =
39 monotonic_clock::now()) {
40 Iterate(monotonic_now - interval_);
41 }
Brian Silvermandcaa3f72015-11-29 05:32:08 +000042
Austin Schuh8aec1ed2016-05-01 13:29:20 -070043 // Calculates the next time to run after monotonic_now.
Brian Silvermandcaa3f72015-11-29 05:32:08 +000044 // The result can be retrieved with sleep_time().
45 // Returns the number of iterations which have passed (1 if this is called
Austin Schuh8aec1ed2016-05-01 13:29:20 -070046 // often enough). This can be < 1 iff monotonic_now goes backwards between
47 // calls.
48 int Iterate(const monotonic_clock::time_point monotonic_now =
49 monotonic_clock::now());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000050
51 // Sleeps until the next time and returns the number of iterations which have
52 // passed.
53 int SleepUntilNext() {
Austin Schuh8aec1ed2016-05-01 13:29:20 -070054 const int r = Iterate(monotonic_clock::now());
55 ::std::this_thread::sleep_until(sleep_time());
Brian Silvermandcaa3f72015-11-29 05:32:08 +000056 return r;
57 }
58
Austin Schuh8aec1ed2016-05-01 13:29:20 -070059 monotonic_clock::time_point sleep_time() const { return last_time_; }
Brian Silvermandcaa3f72015-11-29 05:32:08 +000060
61 private:
Austin Schuh8aec1ed2016-05-01 13:29:20 -070062 const monotonic_clock::duration interval_, offset_;
Brian Silvermandcaa3f72015-11-29 05:32:08 +000063
64 // The time we most recently slept until.
Austin Schuh8aec1ed2016-05-01 13:29:20 -070065 monotonic_clock::time_point last_time_ = monotonic_clock::epoch();
Brian Silvermandcaa3f72015-11-29 05:32:08 +000066};
67
brians343bc112013-02-10 01:53:46 +000068} // namespace time
69} // namespace aos
70
Brian3afd6fc2014-04-02 20:41:49 -070071#endif // AOS_COMMON_UTIL_PHASED_LOOP_H_