Lely core libraries  2.3.4
sigset.hpp
Go to the documentation of this file.
1 
24 #ifndef LELY_IO2_SIGSET_HPP_
25 #define LELY_IO2_SIGSET_HPP_
26 
27 #include <lely/ev/future.hpp>
28 #include <lely/io2/dev.hpp>
29 #include <lely/io2/sigset.h>
30 
31 #include <utility>
32 
33 namespace lely {
34 namespace io {
35 
36 namespace detail {
37 
38 template <class F>
40  public:
41  SignalSetWaitWrapper(ev_exec_t* exec, F&& f)
43  exec,
44  [](ev_task* task) noexcept {
45  auto wait = io_sigset_wait_from_task(task);
46  auto signo = wait->signo;
47  auto self = static_cast<SignalSetWaitWrapper*>(wait);
48  compat::invoke(::std::move(self->func_), signo);
49  delete self;
50  }),
51  func_(::std::forward<F>(f)) {}
52 
54 
55  SignalSetWaitWrapper& operator=(const SignalSetWaitWrapper&) = delete;
56 
57  private:
58  typename ::std::decay<F>::type func_;
59 };
60 
61 } // namespace detail
62 
68 template <class F>
69 inline typename ::std::enable_if<compat::is_invocable<F, int>::value,
72  return new detail::SignalSetWaitWrapper<F>(exec, ::std::forward<F>(f));
73 }
74 
80 class SignalSetWait : public io_sigset_wait {
81  public:
82  using Signature = void(int);
83 
85  template <class F>
86  SignalSetWait(ev_exec_t* exec, F&& f)
89  [](ev_task* task) noexcept {
90  auto wait = io_sigset_wait_from_task(task);
91  auto self = static_cast<SignalSetWait*>(wait);
92  if (self->func_) {
93  auto signo = wait->signo;
94  self->func_(signo);
95  }
96  }),
97  func_(::std::forward<F>(f)) {}
98 
100  template <class F>
101  explicit SignalSetWait(F&& f)
102  : SignalSetWait(nullptr, ::std::forward<F>(f)) {}
103 
104  SignalSetWait(const SignalSetWait&) = delete;
105 
106  SignalSetWait& operator=(const SignalSetWait&) = delete;
107 
108  operator ev_task&() & noexcept { return task; }
109 
112  get_executor() const noexcept {
113  return ev::Executor(task.exec);
114  }
115 
116  private:
117  ::std::function<Signature> func_;
118 };
119 
124 class SignalSetBase : public Device {
125  public:
126  using Device::operator io_dev_t*;
127 
128  explicit SignalSetBase(io_sigset_t* sigset_) noexcept
129  : Device(sigset_ ? io_sigset_get_dev(sigset_) : nullptr),
130  sigset(sigset_) {}
131 
132  operator io_sigset_t*() const noexcept { return sigset; }
133 
135  void
136  clear(::std::error_code& ec) noexcept {
137  int errsv = get_errc();
138  set_errc(0);
139  if (!io_sigset_clear(*this))
140  ec.clear();
141  else
142  ec = util::make_error_code();
143  set_errc(errsv);
144  }
145 
147  void
148  clear() {
149  ::std::error_code ec;
150  clear(ec);
151  if (ec) throw ::std::system_error(ec, "clear");
152  }
153 
155  void
156  insert(int signo, ::std::error_code& ec) noexcept {
157  int errsv = get_errc();
158  set_errc(0);
159  if (!io_sigset_insert(*this, signo))
160  ec.clear();
161  else
162  ec = util::make_error_code();
163  set_errc(errsv);
164  }
165 
167  void
168  insert(int signo) {
169  ::std::error_code ec;
170  insert(signo, ec);
171  if (ec) throw ::std::system_error(ec, "insert");
172  }
173 
175  void
176  remove(int signo, ::std::error_code& ec) noexcept {
177  int errsv = get_errc();
178  set_errc(0);
179  if (!io_sigset_remove(*this, signo))
180  ec.clear();
181  else
182  ec = util::make_error_code();
183  set_errc(errsv);
184  }
185 
187  void
188  remove(int signo) {
189  ::std::error_code ec;
190  remove(signo, ec);
191  if (ec) throw ::std::system_error(ec, "remove");
192  }
193 
195  void
196  submit_wait(io_sigset_wait& wait) noexcept {
197  io_sigset_submit_wait(*this, &wait);
198  }
199 
201  template <class F>
202  void
203  submit_wait(ev_exec_t* exec, F&& f) {
204  submit_wait(*make_signal_set_wait_wrapper(exec, ::std::forward<F>(f)));
205  }
206 
208  template <class F>
209  typename ::std::enable_if<!::std::is_base_of<
210  io_sigset_wait, typename ::std::decay<F>::type>::value>::type
211  submit_wait(F&& f) {
212  submit_wait(nullptr, ::std::forward<F>(f));
213  }
214 
217  async_wait(ev_exec_t* exec, struct io_sigset_wait** pwait = nullptr) {
218  auto future = io_sigset_async_wait(*this, exec, pwait);
219  if (!future) util::throw_errc("async_wait");
220  return ev::Future<int, void>(future);
221  }
222 
225  async_wait(struct io_sigset_wait** pwait = nullptr) {
226  return async_wait(nullptr, pwait);
227  }
228 
229  protected:
230  io_sigset_t* sigset{nullptr};
231 };
232 
233 } // namespace io
234 } // namespace lely
235 
236 #endif // !LELY_IO2_SIGSET_HPP_
IO_SIGSET_WAIT_INIT
#define IO_SIGSET_WAIT_INIT(exec, func)
The static initializer for io_sigset_wait.
Definition: sigset.h:54
dev.hpp
ev_exec_t
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
Definition: ev.h:29
io_sigset_submit_wait
void io_sigset_submit_wait(io_sigset_t *sigset, struct io_sigset_wait *wait)
Submits a wait operation to a signal handler.
Definition: sigset.h:223
lely::io::SignalSetWait::SignalSetWait
SignalSetWait(ev_exec_t *exec, F &&f)
Constructs a wait operation with a completion task.
Definition: sigset.hpp:86
lely::io::SignalSetWait
A wait operation suitable for use with a signal handler.
Definition: sigset.hpp:80
io_sigset_async_wait
ev_future_t * io_sigset_async_wait(io_sigset_t *sigset, ev_exec_t *exec, struct io_sigset_wait **pwait)
Submits an asynchronous wait operation to a signal handler and creates a future which becomes ready o...
Definition: sigset.c:39
io_sigset_wait
A wait operation suitable for use with a signal handler.
Definition: sigset.h:43
lely::io::SignalSetBase::submit_wait
void submit_wait(io_sigset_wait &wait) noexcept
Definition: sigset.hpp:196
lely::io::make_signal_set_wait_wrapper
typename ::std::enable_if< compat::is_invocable< F, int >::value, detail::SignalSetWaitWrapper< F > * >::type make_signal_set_wait_wrapper(ev_exec_t *exec, F &&f)
Creates a wait operation with a completion task.
Definition: sigset.hpp:71
lely::io::SignalSetBase::async_wait
ev::Future< int, void > async_wait(ev_exec_t *exec, struct io_sigset_wait **pwait=nullptr)
Definition: sigset.hpp:217
get_errc
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function.
Definition: errnum.c:932
io_sigset_get_dev
io_dev_t * io_sigset_get_dev(const io_sigset_t *sigset)
Returns a pointer to the abstract I/O device representing the signal handler.
Definition: sigset.h:199
lely::io::SignalSetBase::remove
void remove(int signo)
Definition: sigset.hpp:188
io_sigset_t
const struct io_sigset_vtbl *const io_sigset_t
An abstract signal handler.
Definition: sigset.h:40
lely::io::SignalSetBase::clear
void clear()
Definition: sigset.hpp:148
lely::io::SignalSetWait::get_executor
ev::Executor get_executor() const noexcept
Returns the executor to which the completion task is (to be) submitted.
Definition: sigset.hpp:112
lely::io::SignalSetBase::async_wait
ev::Future< int, void > async_wait(struct io_sigset_wait **pwait=nullptr)
Definition: sigset.hpp:225
lely::io::Device
An abstract I/O device. This class is a wrapper around #io_dev_t*.
Definition: dev.hpp:35
set_errc
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
Definition: errnum.c:944
lely::io::detail::SignalSetWaitWrapper
Definition: sigset.hpp:39
lely::io::SignalSetBase::clear
void clear(::std::error_code &ec) noexcept
Definition: sigset.hpp:136
sigset.h
lely::ev::Executor
An abstract task executor. This class is a wrapper around #ev_exec_t*.
Definition: exec.hpp:38
io_sigset_wait::signo
int signo
The signal number, or 0 if the wait operation was canceled.
Definition: sigset.h:50
lely::ev::Future
A future.
Definition: future.hpp:50
io_sigset_insert
int io_sigset_insert(io_sigset_t *sigset, int signo)
Insert the specified signal number into the set of signals being monitored by a signal handler.
Definition: sigset.h:211
lely::io::SignalSetWait::SignalSetWait
SignalSetWait(F &&f)
Constructs a wait operation with a completion task.
Definition: sigset.hpp:101
lely::io::SignalSetBase::submit_wait
typename ::std::enable_if<!::std::is_base_of< io_sigset_wait, typename ::std::decay< F >::type >::value >::type submit_wait(F &&f)
Definition: sigset.hpp:211
io_sigset_clear
int io_sigset_clear(io_sigset_t *sigset)
Clears the set of signals being monitored by a signal handler.
Definition: sigset.h:205
lely::io::SignalSetBase::remove
void remove(int signo, ::std::error_code &ec) noexcept
Definition: sigset.hpp:176
lely::io::SignalSetBase::insert
void insert(int signo, ::std::error_code &ec) noexcept
Definition: sigset.hpp:156
future.hpp
lely::io::SignalSetBase::submit_wait
void submit_wait(ev_exec_t *exec, F &&f)
Definition: sigset.hpp:203
ev_task
An executable task.
Definition: task.h:41
io_sigset_wait_from_task
struct io_sigset_wait * io_sigset_wait_from_task(struct ev_task *task)
Obtains a pointer to a signal wait operation from a pointer to its completion task.
Definition: sigset.c:62
io_dev_t
const struct io_dev_vtbl *const io_dev_t
An abstract I/O device.
Definition: dev.h:35
io_sigset_remove
int io_sigset_remove(io_sigset_t *sigset, int signo)
Removes the specified signal number from the set of signals being monitored by a signal handler.
Definition: sigset.h:217
lely::canopen::make_error_code
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
Definition: sdo_error.cpp:170
io_sigset_wait::task
struct ev_task task
The task (to be) submitted upon completion (or cancellation) of the wait operation.
Definition: sigset.h:48
ev_task::exec
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
Definition: task.h:43
lely::io::SignalSetBase
A reference to an abstract signal handler.
Definition: sigset.hpp:124
lely::io::SignalSetBase::insert
void insert(int signo)
Definition: sigset.hpp:168