FINAL CUT
monitor.h
1 /***********************************************************************
2 * monitor.h - Monitoring object base class *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2023-2026 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 /* Base class
24  * ══════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▏
27  * ▕ Monitor ▏
28  * ▕▁▁▁▁▁▁▁▁▁▏
29  */
30 
31 #ifndef MONITOR_H
32 #define MONITOR_H
33 
34 #include <atomic>
35 #include <functional>
36 #include <stdexcept>
37 #include <string>
38 
39 #include "final/util/fdata.h"
40 #include "final/util/fstring.h"
41 
42 namespace finalcut
43 {
44 
45 // class forward declaration
46 class EventLoop;
47 class Monitor;
48 
49 //----------------------------------------------------------------------
50 // class monitor_error
51 //----------------------------------------------------------------------
52 
53 class monitor_error : public std::runtime_error
54 {
55  public:
56  using std::runtime_error::runtime_error;
57 
58  // Copy constructor
59  monitor_error (const monitor_error&) = default;
60 
61  // Move constructor
62  monitor_error (monitor_error&&) noexcept = default;
63 
64  // Copy assignment operator (=)
65  auto operator = (const monitor_error&) -> monitor_error& = default;
66 
67  // Move assignment operator (=)
68  auto operator = (monitor_error&&) noexcept -> monitor_error& = default;
69 
70  // Destructor
71  ~monitor_error() override;
72 };
73 
74 // Using-declaration
75 using handler_t = std::function<void(Monitor*, short)>;
76 
77 
78 //----------------------------------------------------------------------
79 // class Monitor
80 //----------------------------------------------------------------------
81 
82 class Monitor
83 {
84  public:
85  // Enumeration
86  enum class State : uInt8
87  {
88  Inactive,
89  Active,
90  Suspended
91  };
92 
93  // Constructor
94  explicit Monitor (EventLoop*);
95  Monitor() = delete;
96 
97  // Disable copy constructor
98  Monitor (const Monitor&) = delete;
99 
100  // Disable move constructor
101  Monitor (Monitor&&) noexcept = delete;
102 
103  // Destructor
104  virtual ~Monitor();
105 
106  // Disable copy assignment operator (=)
107  auto operator = (const Monitor&) -> Monitor& = delete;
108 
109  // Disable move assignment operator (=)
110  auto operator = (Monitor&&) noexcept -> Monitor& = delete;
111 
112  // Accessors
113  virtual auto getClassName() const -> FString;
114  auto getEvents() const noexcept -> short;
115  auto getFileDescriptor() const noexcept -> int;
116  template <typename T>
117  auto getUserContext() const -> clean_fdata_t<T>&;
118 
119  // Predicate
120  auto isActive() const noexcept -> bool;
121  auto isSuspended() const noexcept -> bool;
122  auto hasValidFileDescriptor() const noexcept -> bool;
123  auto hasHandler() const noexcept -> bool;
124 
125  // Methods
126  virtual void resume() noexcept;
127  virtual void suspend() noexcept;
128  virtual void deactivate() noexcept;
129 
130  protected:
131  // Constant
132  static constexpr int NO_FILE_DESCRIPTOR{-1};
133 
134  // Mutators
135  void setFileDescriptor (int) noexcept;
136  void setEvents (short) noexcept;
137  void setHandler (handler_t&&) noexcept;
138  void setHandler (const handler_t& handler);
139  template <typename T>
140  void setUserContext (T&&) noexcept;
141  void clearUserContext() noexcept;
142  void setInitialized() noexcept;
143 
144  // Predicate
145  auto isInitialized() const -> bool;
146 
147  // Methods
148  virtual void trigger (short);
149 
150  private:
151  // Using-declaration
152  using FDataAccessPtr = std::shared_ptr<FDataAccess>;
153 
154  // Accessors
155  auto getState() const noexcept -> State;
156 
157  // Methods
158  void validateEventLoop() const;
159  void setState (State) noexcept;
160 
161  // Data member
162  EventLoop* eventloop{};
163  std::atomic<State> state{State::Inactive};
164  std::atomic<int> fd{NO_FILE_DESCRIPTOR};
165  std::atomic<short> events{0};
166  std::atomic<bool> monitor_initialized{false};
167  handler_t handler{};
168  FDataAccessPtr user_context{nullptr};
169 
170  // Friend classes
171  friend class EventLoop;
172 };
173 
174 // Monitor inline functions
175 //----------------------------------------------------------------------
176 inline auto Monitor::getClassName() const -> FString
177 { return "Monitor"; }
178 
179 //----------------------------------------------------------------------
180 inline auto Monitor::getEvents() const noexcept -> short
181 { return events.load(); }
182 
183 //----------------------------------------------------------------------
184 inline auto Monitor::getFileDescriptor() const noexcept -> int
185 { return fd.load(); }
186 
187 //----------------------------------------------------------------------
188 template <typename T>
189 auto Monitor::getUserContext() const -> clean_fdata_t<T>&
190 {
191  static T empty_lvalue = T{};
192  return user_context
193  ? static_cast<FData<clean_fdata_t<T>>&>(*user_context).get()
194  : empty_lvalue;
195 }
196 
197 //----------------------------------------------------------------------
198 inline auto Monitor::isActive() const noexcept -> bool
199 { return getState() == State::Active; }
200 
201 //----------------------------------------------------------------------
202 inline auto Monitor::isSuspended() const noexcept -> bool
203 { return getState() == State::Suspended; }
204 
205 //----------------------------------------------------------------------
206 inline auto Monitor::hasValidFileDescriptor() const noexcept -> bool
207 { return fd.load() != NO_FILE_DESCRIPTOR; }
208 
209 //----------------------------------------------------------------------
210 inline auto Monitor::hasHandler() const noexcept -> bool
211 { return static_cast<bool>(handler); }
212 
213 //----------------------------------------------------------------------
214 inline void Monitor::resume() noexcept
215 { setState(State::Active); }
216 
217 //----------------------------------------------------------------------
218 inline void Monitor::suspend() noexcept
219 { setState(State::Suspended); }
220 
221 //----------------------------------------------------------------------
222 inline void Monitor::deactivate() noexcept
223 { setState(State::Inactive); }
224 
225 //----------------------------------------------------------------------
226 inline void Monitor::trigger (short return_events)
227 {
228  if ( ! handler || ! isActive() )
229  return;
230 
231  try
232  {
233  handler (this, return_events);
234  }
235  catch (...)
236  {
237  suspend();
238  throw; // Re-throw other errors
239  }
240 }
241 
242 //----------------------------------------------------------------------
243 inline void Monitor::setFileDescriptor (int file_descriptor) noexcept
244 { fd.store(file_descriptor); }
245 
246 //----------------------------------------------------------------------
247 inline void Monitor::setEvents (short ev) noexcept
248 { events.store(ev); }
249 
250 //----------------------------------------------------------------------
251 inline void Monitor::setHandler (handler_t&& hdl) noexcept
252 { handler = std::move(hdl); }
253 
254 //----------------------------------------------------------------------
255 inline void Monitor::setHandler(const handler_t& hdl)
256 { handler = hdl; }
257 
258 //----------------------------------------------------------------------
259 template <typename T>
260 inline void Monitor::setUserContext (T&& uc) noexcept
261 { user_context = makeFData(std::forward<T>(uc)); }
262 
263 //----------------------------------------------------------------------
264 inline void Monitor::clearUserContext() noexcept
265 { user_context.reset(); }
266 
267 //----------------------------------------------------------------------
268 inline void Monitor::setInitialized() noexcept
269 { monitor_initialized.store(true); }
270 
271 //----------------------------------------------------------------------
272 inline auto Monitor::isInitialized() const -> bool
273 { return monitor_initialized.load(); }
274 
275 //----------------------------------------------------------------------
276 inline auto Monitor::getState() const noexcept -> State
277 { return state.load(); }
278 
279 //----------------------------------------------------------------------
280 inline void Monitor::setState (State new_state) noexcept
281 { state.store(new_state); }
282 
283 } // namespace finalcut
284 
285 #endif // MONITOR_H
Definition: monitor.h:82
Definition: eventloop.h:49
Definition: class_template.cpp:25
Definition: monitor.h:53
Definition: fstring.h:82
Definition: fdata.h:55