FINAL CUT
timer_monitor.h
1 /***********************************************************************
2 * timer_monitor.h - Time monitoring object *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2023 Andreas Noe *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Inheritance diagram
24  * ═══════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▏
27  * ▕ Monitor ▏
28  * ▕▁▁▁▁▁▁▁▁▁▏
29  * ▲
30  * │
31  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
32  * ▕ TimerMonitorImpl ▏
33  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
34  * ▲ ▲
35  * │ │
36  * ▕▔▔▔▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏
37  * ▕ PipeData ▏- - -▕ PosixTimer ▏ ▕ KqueueTimer ▏ (platform-specific)
38  * ▕▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏
39  * ▲ ▲
40  * │ │
41  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏
42  * ▕ TimerMonitor ▏
43  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏
44  */
45 
46 #ifndef TIMER_MONITOR_H
47 #define TIMER_MONITOR_H
48 
49 #if (defined(__APPLE__) && defined(__MACH__)) || defined(__OpenBSD__)
50  #define USE_KQUEUE_TIMER
51  #include <unistd.h>
52  #include <sys/event.h>
53  #include <sys/types.h>
54 #else
55  #define USE_POSIX_TIMER
56 #endif
57 
58 #include <ctime>
59 
60 #include <chrono>
61 #include <vector>
62 
63 #include "final/eventloop/monitor.h"
64 #include "final/eventloop/pipedata.h"
65 #include "final/ftypes.h"
66 
67 namespace finalcut
68 {
69 
70 // class and struct forward declaration
71 class SigAlrmHandlerInstaller;
72 struct KqueueHandlerInstaller;
73 
74 //----------------------------------------------------------------------
75 // class TimerMonitorImpl
76 //----------------------------------------------------------------------
77 class TimerMonitorImpl : public Monitor
78 {
79  public:
80  // Using-declaration
81  using Monitor::Monitor;
82 
83  // Destructor
84  ~TimerMonitorImpl() override;
85 
86  // Methods
87  virtual void setInterval ( std::chrono::nanoseconds
88  , std::chrono::nanoseconds ) = 0;
89 };
90 
91 
92 //----------------------------------------------------------------------
93 // class PosixTimer
94 //----------------------------------------------------------------------
96 {
97  public:
98  // Using-declaration
99  using TimerMonitorImpl::TimerMonitorImpl;
100 
101  // Constructor
102  explicit PosixTimer (EventLoop*);
103 
104  // Disable copy constructor
105  PosixTimer (const PosixTimer&) = delete;
106 
107  // Disable move constructor
108  PosixTimer (PosixTimer&&) noexcept = delete;
109 
110  // Destructor
111  ~PosixTimer() noexcept override;
112 
113  // Disable copy assignment operator (=)
114  auto operator = (const PosixTimer&) -> PosixTimer& = delete;
115 
116  // Disable move assignment operator (=)
117  auto operator = (PosixTimer&&) noexcept -> PosixTimer& = delete;
118 
119  // Methods
120  template <typename T>
121  void init (handler_t, T&&);
122  void setInterval ( std::chrono::nanoseconds
123  , std::chrono::nanoseconds ) override;
124  void trigger(short) override;
125 
126  private:
127  void init();
128  void createAlarmPipe();
129  void installTime();
130 
131 #if defined(USE_POSIX_TIMER)
132  // Data members
133  timer_t timer_id{};
134  PipeData alarm_pipe{NO_FILE_DESCRIPTOR, NO_FILE_DESCRIPTOR};
135  static SigAlrmHandlerInstaller* sig_alrm_handler_installer;
136 #endif // defined(USE_POSIX_TIMER)
137 };
138 
139 #if defined(USE_POSIX_TIMER)
140 //----------------------------------------------------------------------
141 template <typename T>
142 inline void PosixTimer::init (handler_t hdl, T&& uc)
143 {
144  if ( isInitialized() )
145  throw monitor_error{"This instance has already been initialised."};
146 
147  setHandler (std::move(hdl));
148  setUserContext (std::forward<T>(uc));
149  init();
150 }
151 #endif // defined(USE_POSIX_TIMER)
152 
153 
154 //----------------------------------------------------------------------
155 // class KqueueTimer
156 //----------------------------------------------------------------------
157 
159 {
160  public:
161  // Using-declaration
162  using TimerMonitorImpl::TimerMonitorImpl;
163 
164  // Constructor
165  explicit KqueueTimer (EventLoop*);
166 
167  // Disable copy constructor
168  KqueueTimer (const KqueueTimer&) = delete;
169 
170  // Disable move constructor
171  KqueueTimer (KqueueTimer&&) noexcept = delete;
172 
173  // Destructor
174  ~KqueueTimer() noexcept override;
175 
176  // Disable copy assignment operator (=)
177  auto operator = (const KqueueTimer&) -> KqueueTimer& = delete;
178 
179  // Disable move assignment operator (=)
180  auto operator = (KqueueTimer&&) noexcept -> KqueueTimer& = delete;
181 
182  // Methods
183  template <typename T>
184  void init (handler_t, T&&);
185  void setInterval ( std::chrono::nanoseconds
186  , std::chrono::nanoseconds ) override;
187  void trigger(short) override;
188 
189  private:
190  void init();
191 
192 #if defined(USE_KQUEUE_TIMER) || defined(UNIT_TEST)
193  struct TimerSpec
194  {
195  int period_ms{};
196  int first_ms{};
197  };
198 
199  // Constants
200  static constexpr int NO_TIMER_ID{-1};
201 
202  // Data members
203  int timer_id{NO_TIMER_ID};
204  bool first_interval{true};
205  TimerSpec timer_spec{};
206  handler_t timer_handler{};
207  static KqueueHandlerInstaller* kqueue_handler_installer;
208 
209  // Friend classes
210  friend class KqueueHandler;
211 #endif // defined(USE_KQUEUE_TIMER)
212 };
213 
214 #if defined(USE_KQUEUE_TIMER) || defined(UNIT_TEST)
215 //----------------------------------------------------------------------
216 template <typename T>
217 inline void KqueueTimer::init (handler_t hdl, T&& uc)
218 {
219  if ( isInitialized() )
220  throw monitor_error{"This instance has already been initialised."};
221 
222  timer_handler = std::move(hdl);
223  setUserContext (std::forward<T>(uc));
224  init();
225 }
226 #endif // defined(USE_KQUEUE_TIMER)
227 
228 
229 //----------------------------------------------------------------------
230 // struct TimerClass
231 //----------------------------------------------------------------------
232 
234 {
235  #if defined(__APPLE__) && defined(__MACH__)
236  using type = KqueueTimer;
237  #elif defined(__OpenBSD__)
238  using type = KqueueTimer;
239  #else
240  using type = PosixTimer;
241  #endif
242 };
243 
244 
245 //----------------------------------------------------------------------
246 // class TimerMonitor
247 //----------------------------------------------------------------------
248 
249 class TimerMonitor final : public TimerClass::type
250 {
251  public:
252  // Using-declarations
254  using base_class::base_class;
255 
256  TimerMonitor() = delete;
257 
258  // Disable copy constructor
259  TimerMonitor (const TimerMonitor&) = delete;
260 
261  // Disable move constructor
262  TimerMonitor (TimerMonitor&&) noexcept = delete;
263 
264  // Destructor
265  ~TimerMonitor() override;
266 
267  // Disable copy assignment operator (=)
268  auto operator = (const TimerMonitor&) -> TimerMonitor& = delete;
269 
270  // Disable move assignment operator (=)
271  auto operator = (TimerMonitor&&) noexcept -> TimerMonitor& = delete;
272 
273  // Accessor
274  auto getClassName() const -> FString override;
275 };
276 
277 // TimerMonitor inline functions
278 //----------------------------------------------------------------------
279 inline auto TimerMonitor::getClassName() const -> FString
280 { return "TimerMonitor"; }
281 
282 } // namespace finalcut
283 
284 #endif // TIMER_MONITOR_H
Definition: timer_monitor.h:249
Definition: monitor.h:81
Definition: eventloop.h:48
Definition: class_template.cpp:25
Definition: timer_monitor.h:77
Definition: monitor.h:52
Definition: posix_timer.cpp:169
Definition: timer_monitor.h:95
Definition: fstring.h:79
Definition: timer_monitor.h:158
Definition: pipedata.h:47
Definition: timer_monitor.h:233