FINAL CUT
signal_monitor.h
1 /***********************************************************************
2 * signal_monitor.h - Signal monitoring object *
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 /* Inheritance diagram
24  * ═══════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▏
27  * ▕ Monitor ▏
28  * ▕▁▁▁▁▁▁▁▁▁▏
29  * ▲
30  * │
31  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏1 1▕▔▔▔▔▔▔▔▔▔▔▏
32  * ▕ SignalMonitor ▏- - - - -▕ PipeData ▏
33  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▏
34  */
35 
36 #ifndef SIGNAL_MONITOR_H
37 #define SIGNAL_MONITOR_H
38 
39 #include <map>
40 #include <memory>
41 
42 #include "final/eventloop/monitor.h"
43 #include "final/eventloop/pipedata.h"
44 #include "final/util/fstring.h"
45 
46 namespace finalcut
47 {
48 
49 //----------------------------------------------------------------------
50 // class SignalMonitor
51 //----------------------------------------------------------------------
52 
53 class SignalMonitor final : public Monitor
54 {
55  public:
56  explicit SignalMonitor(EventLoop*);
57 
58  // Disable default constructor
59  SignalMonitor() = delete;
60 
61  // Disable copy constructor
62  SignalMonitor (const SignalMonitor&) = delete;
63 
64  // Disable move constructor
65  SignalMonitor (SignalMonitor&&) = delete;
66 
67  // Destructor
68  ~SignalMonitor() noexcept override;
69 
70  // Disable copy assignment operator (=)
71  auto operator = (const SignalMonitor&) -> SignalMonitor& = delete;
72 
73  // Disable move assignment operator (=)
74  auto operator = (SignalMonitor&&) noexcept -> SignalMonitor& = delete;
75 
76  // Accessor
77  auto getClassName() const -> FString override;
78 
79  // Methods
80  template <typename T>
81  void init (int, handler_t, T&&);
82  void trigger (short) override;
83 
84  private:
85  // class forward declaration
86  class SigactionImpl;
87 
88  // Constants
89  static constexpr int INVALID_SIGNAL{-1};
90  static constexpr std::uint64_t SIGNAL_NOTIFICATION{1U};
91 
92 #if defined(NSIG) && (NSIG > 0)
93  static constexpr int NUMBER_OF_SIGNALS{NSIG};
94 #elif defined(_NSIG) && (_NSIG > 0)
95  static constexpr int NUMBER_OF_SIGNALS{_NSIG};
96 #else
97  static constexpr int NUMBER_OF_SIGNALS{65}; // Fallback value
98 #endif
99 
100  // Accessor
101  auto getSigactionImpl() const -> const SigactionImpl*;
102  auto getSigactionImpl() -> SigactionImpl*;
103 
104  // Methods
105  static void onSignal (int) noexcept;
106  void init();
107  void validate (int, const handler_t&) const;
108  void handledAlarmSignal() const;
109  void ensureSignalIsUnmonitored() const;
110  void createPipe();
111  void installSignalHandler();
112  void cleanupResources() noexcept;
113  void enterMonitorInstanceInTable();
114 
115  // Data members
116  int signal_number{INVALID_SIGNAL};
117  PipeData signal_pipe{NO_FILE_DESCRIPTOR, NO_FILE_DESCRIPTOR};
118  std::unique_ptr<SigactionImpl> impl;
119 };
120 
121 // SignalMonitor inline functions
122 //----------------------------------------------------------------------
123 inline auto SignalMonitor::getClassName() const -> FString
124 { return "SignalMonitor"; }
125 
126 //----------------------------------------------------------------------
127 inline auto SignalMonitor::getSigactionImpl() const -> const SigactionImpl*
128 { return impl.get(); }
129 
130 //----------------------------------------------------------------------
131 inline auto SignalMonitor::getSigactionImpl() -> SigactionImpl*
132 { return impl.get(); }
133 
134 //----------------------------------------------------------------------
135 template <typename T>
136 inline void SignalMonitor::init (int sn, handler_t hdl, T&& uc)
137 {
138  try
139  {
140  validate(sn, hdl);
141  signal_number = sn;
142  setHandler (std::move(hdl));
143  setUserContext (std::forward<T>(uc));
144  init();
145  }
146  catch (...)
147  {
148  signal_number = INVALID_SIGNAL; // Clear signal number
149  setHandler(handler_t{}); // Clear handler
150  clearUserContext(); // Clear user context
151  cleanupResources();
152  throw; // Re-throw the original exception
153  }
154 }
155 
156 //----------------------------------------------------------------------
157 inline void SignalMonitor::validate (int sn, const handler_t& hdl) const
158 {
159  if ( isInitialized() )
160  throw monitor_error{"This instance has already been initialised."};
161 
162  if ( sn <= 0 || sn >= NUMBER_OF_SIGNALS )
163  throw monitor_error{ "Invalid signal number: must be > 0 and < "
164  + std::to_string(NUMBER_OF_SIGNALS) };
165 
166  if ( ! hdl )
167  throw monitor_error{"Handler cannot be null"};
168 }
169 
170 } // namespace finalcut
171 
172 #endif // SIGNAL_MONITOR_H
Definition: signal_monitor.h:53
Definition: monitor.h:82
Definition: eventloop.h:49
Definition: class_template.cpp:25
Definition: monitor.h:53
Definition: signal_monitor.cpp:66
Definition: fstring.h:82
Definition: pipedata.h:48