MADARA  3.2.3
SimTime.cpp
Go to the documentation of this file.
1 #include "SimTime.h"
2 
3 #ifdef MADARA_FEATURE_SIMTIME
4 
5 #include <chrono>
6 #include <cmath>
7 
8 namespace madara { namespace utility {
9 
10 const double minrate = 0.0000000001;
11 
12 std::mutex SimTime::mutex_{};
13 
14 sim_time_callback_fn SimTime::callback_ = nullptr;
15 
16 uint64_t SimTime::last_realtime_ = SimTime::realtime();
17 uint64_t SimTime::last_simtime_ = -1;
18 double SimTime::last_rate_ = 1.0;
19 
20 uint64_t SimTime::realtime() {
21  namespace sc = std::chrono;
22  auto now = sc::steady_clock::now();
23  auto dur = now.time_since_epoch();
24  return sc::duration_cast<sc::nanoseconds>(dur).count();
25 }
26 
27 uint64_t SimTime::time() {
28  uint64_t prt;
29  uint64_t pst;
30  double pr;
31  uint64_t st;
32  double r;
33  sim_time_callback_fn callback;
34 
35  uint64_t now = realtime();
36  {
37  std::lock_guard<std::mutex> guard{mutex_};
38  callback = callback_;
39  if (callback) {
40  callback_(&st, &r);
41 
42  last_realtime_ = now;
43  last_simtime_ = st;
44  last_rate_ = r;
45  } else {
46  prt = last_realtime_;
47  pst = last_simtime_;
48  pr = last_rate_;
49  }
50  }
51 
52  if (!callback) {
53  if (pst == (uint64_t)-1) {
54  return now;
55  }
56  if (pr == 0) {
57  return pst;
58  }
59 
60  int64_t offset = now - prt;
61 
62  if (pr < minrate) {
63  pr = minrate;
64  }
65 
66  double delta = offset * pr;
67  st = pst + (int64_t)delta;
68  }
69 
70  return st;
71 }
72 
73 double SimTime::rate() {
74  double r;
75  sim_time_callback_fn callback;
76 
77  {
78  std::lock_guard<std::mutex> guard{mutex_};
79  callback = callback_;
80 
81  if (callback) {
82  callback(nullptr, &r);
83  } else {
84  r = last_rate_;
85  }
86  }
87 
88  return r;
89 }
90 
91 uint64_t SimTime::duration(uint64_t sim_duration) {
92  double r = rate();
93 
94  if (r < minrate) {
95  return -1;
96  }
97 
98  return sim_duration / r;
99 }
100 
101 uint64_t SimTime::future(uint64_t sim_offset) {
102  uint64_t now = realtime();
103  uint64_t offset = duration(sim_offset);
104 
105  if (offset == (uint64_t)-1) {
106  return -1;
107  }
108 
109  return now + offset;
110 }
111 
112 sim_time_callback_fn set_sim_time_callback(sim_time_callback_fn fn) {
113  std::lock_guard<std::mutex> guard{SimTime::mutex_};
114  using std::swap;
115  swap (fn, SimTime::callback_);
116  return fn;
117 }
118 
119 void sim_time_notify(uint64_t time, double rate) {
120  bool update_time = time != (uint64_t)-1;
121  bool update_rate = !std::isnan(rate);
122 
123  if (!update_time && !update_rate) {
124  return;
125  }
126 
127  uint64_t now = SimTime::realtime();
128  std::lock_guard<std::mutex> guard{SimTime::mutex_};
129 
130  if (update_time) {
131  SimTime::last_realtime_ = now;
132  SimTime::last_simtime_ = time;
133  } else if (SimTime::last_simtime_ == (uint64_t)-1) {
134  SimTime::last_realtime_ = now;
135  SimTime::last_simtime_ = now;
136  }
137 
138  if (update_rate) {
139  SimTime::last_rate_ = rate;
140  }
141 }
142 
143 } }
144 
145 #endif
Provides utility functions and classes for common tasks and needs.
Definition: IteratorImpl.h:14
Copyright (c) 2015 Carnegie Mellon University.