scenario_simulator_v2 C++ API
status_monitor.hpp
Go to the documentation of this file.
1 // Copyright 2015 TIER IV, Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef STATUS_MONITOR__STATUS_MONITOR_HPP_
16 #define STATUS_MONITOR__STATUS_MONITOR_HPP_
17 
18 #include <cerrno>
19 #include <chrono>
20 #include <filesystem>
21 #include <fstream>
22 #include <mutex>
23 #include <thread>
24 #include <unordered_map>
25 #include <utility>
26 
27 namespace common
28 {
30 {
31  struct Status
32  {
33  const std::string name;
34 
35  std::chrono::high_resolution_clock::time_point last_access;
36 
37  using duration = std::chrono::high_resolution_clock::duration;
38 
39  duration minimum_access_interval;
40 
41  duration maximum_access_interval;
42 
43  bool exited = false;
44 
45  template <typename Name>
46  explicit Status(Name && name)
47  : name(std::forward<decltype(name)>(name)),
48  last_access(std::chrono::high_resolution_clock::now()),
49  minimum_access_interval(duration::max()),
50  maximum_access_interval(duration::min())
51  {
52  }
53 
54  auto since_last_access() const
55  {
56  return std::chrono::high_resolution_clock::now() - last_access;
57  }
58 
59  auto good() const { return exited or since_last_access() < threshold; }
60 
61  explicit operator bool() const { return good(); }
62  };
63 
64  static inline std::ofstream file;
65 
66  static inline std::unordered_map<std::thread::id, Status> statuses;
67 
68  static inline std::thread watchdog;
69 
70  static inline std::atomic_bool terminating;
71 
72  static inline std::chrono::seconds threshold = std::chrono::seconds(10);
73 
74  static inline std::mutex mutex;
75 
76 public:
77  explicit StatusMonitor();
78 
80 
81  template <typename Name>
82  auto touch(Name && name)
83  {
84  auto lock = std::scoped_lock<std::mutex>(mutex);
85 
86  if (auto iter = statuses.find(std::this_thread::get_id()); iter != std::end(statuses)) {
87  [[maybe_unused]] auto && [id, status] = *iter;
88 
89  const auto now = std::chrono::high_resolution_clock::now();
90 
91  const auto this_access_interval = now - status.last_access;
92 
93  status.minimum_access_interval =
94  std::min(status.minimum_access_interval, this_access_interval);
95 
96  status.maximum_access_interval =
97  std::max(status.maximum_access_interval, this_access_interval);
98 
99  status.last_access = now;
100  } else {
101  statuses.emplace(std::this_thread::get_id(), std::forward<decltype(name)>(name));
102  }
103  }
104 
105  template <typename T>
107  {
108  std::reference_wrapper<T> target;
109 
110  T value;
111 
112  public:
113  template <typename... Ts>
114  static auto locked_exchange(Ts &&... xs) -> decltype(auto)
115  {
116  auto lock = std::scoped_lock<std::mutex>(mutex);
117  return std::exchange(std::forward<decltype(xs)>(xs)...);
118  }
119 
120  template <typename U>
121  explicit ScopedExchanger(T & x, U && y)
122  : target(x), value(locked_exchange(target.get(), std::forward<decltype(y)>(y)))
123  {
124  }
125 
126  ~ScopedExchanger() { locked_exchange(target.get(), value); }
127  };
128 
130  {
132  explicit ScopedUpdater(StatusMonitor & m) : monitor(m) { monitor.touch(""); }
134  };
135 
136  template <typename Thunk>
137  auto overrideThreshold(const std::chrono::seconds & t, Thunk thunk) -> decltype(auto)
138  {
139  auto exchanger = ScopedExchanger(threshold, t);
140  auto updater = ScopedUpdater(*this);
141 
142  return thunk();
143  }
144 
145  auto write() const -> void;
146 } static status_monitor;
147 } // namespace common
148 
149 #endif // STATUS_MONITOR__STATUS_MONITOR_HPP_
Definition: status_monitor.hpp:107
ScopedExchanger(T &x, U &&y)
Definition: status_monitor.hpp:121
static auto locked_exchange(Ts &&... xs) -> decltype(auto)
Definition: status_monitor.hpp:114
~ScopedExchanger()
Definition: status_monitor.hpp:126
Definition: status_monitor.hpp:30
auto write() const -> void
Definition: status_monitor.cpp:81
~StatusMonitor()
Definition: status_monitor.cpp:60
auto overrideThreshold(const std::chrono::seconds &t, Thunk thunk) -> decltype(auto)
Definition: status_monitor.hpp:137
auto touch(Name &&name)
Definition: status_monitor.hpp:82
StatusMonitor()
Definition: status_monitor.cpp:39
Definition: concatenate.hpp:24
class common::StatusMonitor status_monitor
Definition: lanelet_wrapper.hpp:40
Definition: junit5.hpp:25
std::string string
Definition: junit5.hpp:26
Definition: status_monitor.hpp:130
~ScopedUpdater()
Definition: status_monitor.hpp:133
StatusMonitor & monitor
Definition: status_monitor.hpp:131
ScopedUpdater(StatusMonitor &m)
Definition: status_monitor.hpp:132
TrafficLight::Status Status
Definition: test_traffic_light.cpp:26