basic_signal_set.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. //
  2. // basic_signal_set.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef ASIO_BASIC_SIGNAL_SET_HPP
  11. #define ASIO_BASIC_SIGNAL_SET_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/basic_io_object.hpp"
  17. #include "asio/detail/handler_type_requirements.hpp"
  18. #include "asio/detail/throw_error.hpp"
  19. #include "asio/error.hpp"
  20. #include "asio/signal_set_service.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. namespace asio {
  23. /// Provides signal functionality.
  24. /**
  25. * The basic_signal_set class template provides the ability to perform an
  26. * asynchronous wait for one or more signals to occur.
  27. *
  28. * Most applications will use the asio::signal_set typedef.
  29. *
  30. * @par Thread Safety
  31. * @e Distinct @e objects: Safe.@n
  32. * @e Shared @e objects: Unsafe.
  33. *
  34. * @par Example
  35. * Performing an asynchronous wait:
  36. * @code
  37. * void handler(
  38. * const asio::error_code& error,
  39. * int signal_number)
  40. * {
  41. * if (!error)
  42. * {
  43. * // A signal occurred.
  44. * }
  45. * }
  46. *
  47. * ...
  48. *
  49. * // Construct a signal set registered for process termination.
  50. * asio::signal_set signals(io_service, SIGINT, SIGTERM);
  51. *
  52. * // Start an asynchronous wait for one of the signals to occur.
  53. * signals.async_wait(handler);
  54. * @endcode
  55. *
  56. * @par Queueing of signal notifications
  57. *
  58. * If a signal is registered with a signal_set, and the signal occurs when
  59. * there are no waiting handlers, then the signal notification is queued. The
  60. * next async_wait operation on that signal_set will dequeue the notification.
  61. * If multiple notifications are queued, subsequent async_wait operations
  62. * dequeue them one at a time. Signal notifications are dequeued in order of
  63. * ascending signal number.
  64. *
  65. * If a signal number is removed from a signal_set (using the @c remove or @c
  66. * erase member functions) then any queued notifications for that signal are
  67. * discarded.
  68. *
  69. * @par Multiple registration of signals
  70. *
  71. * The same signal number may be registered with different signal_set objects.
  72. * When the signal occurs, one handler is called for each signal_set object.
  73. *
  74. * Note that multiple registration only works for signals that are registered
  75. * using Asio. The application must not also register a signal handler using
  76. * functions such as @c signal() or @c sigaction().
  77. *
  78. * @par Signal masking on POSIX platforms
  79. *
  80. * POSIX allows signals to be blocked using functions such as @c sigprocmask()
  81. * and @c pthread_sigmask(). For signals to be delivered, programs must ensure
  82. * that any signals registered using signal_set objects are unblocked in at
  83. * least one thread.
  84. */
  85. template <typename SignalSetService = signal_set_service>
  86. class basic_signal_set
  87. : public basic_io_object<SignalSetService>
  88. {
  89. public:
  90. /// Construct a signal set without adding any signals.
  91. /**
  92. * This constructor creates a signal set without registering for any signals.
  93. *
  94. * @param io_service The io_service object that the signal set will use to
  95. * dispatch handlers for any asynchronous operations performed on the set.
  96. */
  97. explicit basic_signal_set(asio::io_service& io_service)
  98. : basic_io_object<SignalSetService>(io_service)
  99. {
  100. }
  101. /// Construct a signal set and add one signal.
  102. /**
  103. * This constructor creates a signal set and registers for one signal.
  104. *
  105. * @param io_service The io_service object that the signal set will use to
  106. * dispatch handlers for any asynchronous operations performed on the set.
  107. *
  108. * @param signal_number_1 The signal number to be added.
  109. *
  110. * @note This constructor is equivalent to performing:
  111. * @code asio::signal_set signals(io_service);
  112. * signals.add(signal_number_1); @endcode
  113. */
  114. basic_signal_set(asio::io_service& io_service, int signal_number_1)
  115. : basic_io_object<SignalSetService>(io_service)
  116. {
  117. asio::error_code ec;
  118. this->service.add(this->implementation, signal_number_1, ec);
  119. asio::detail::throw_error(ec, "add");
  120. }
  121. /// Construct a signal set and add two signals.
  122. /**
  123. * This constructor creates a signal set and registers for two signals.
  124. *
  125. * @param io_service The io_service object that the signal set will use to
  126. * dispatch handlers for any asynchronous operations performed on the set.
  127. *
  128. * @param signal_number_1 The first signal number to be added.
  129. *
  130. * @param signal_number_2 The second signal number to be added.
  131. *
  132. * @note This constructor is equivalent to performing:
  133. * @code asio::signal_set signals(io_service);
  134. * signals.add(signal_number_1);
  135. * signals.add(signal_number_2); @endcode
  136. */
  137. basic_signal_set(asio::io_service& io_service, int signal_number_1,
  138. int signal_number_2)
  139. : basic_io_object<SignalSetService>(io_service)
  140. {
  141. asio::error_code ec;
  142. this->service.add(this->implementation, signal_number_1, ec);
  143. asio::detail::throw_error(ec, "add");
  144. this->service.add(this->implementation, signal_number_2, ec);
  145. asio::detail::throw_error(ec, "add");
  146. }
  147. /// Construct a signal set and add three signals.
  148. /**
  149. * This constructor creates a signal set and registers for three signals.
  150. *
  151. * @param io_service The io_service object that the signal set will use to
  152. * dispatch handlers for any asynchronous operations performed on the set.
  153. *
  154. * @param signal_number_1 The first signal number to be added.
  155. *
  156. * @param signal_number_2 The second signal number to be added.
  157. *
  158. * @param signal_number_3 The third signal number to be added.
  159. *
  160. * @note This constructor is equivalent to performing:
  161. * @code asio::signal_set signals(io_service);
  162. * signals.add(signal_number_1);
  163. * signals.add(signal_number_2);
  164. * signals.add(signal_number_3); @endcode
  165. */
  166. basic_signal_set(asio::io_service& io_service, int signal_number_1,
  167. int signal_number_2, int signal_number_3)
  168. : basic_io_object<SignalSetService>(io_service)
  169. {
  170. asio::error_code ec;
  171. this->service.add(this->implementation, signal_number_1, ec);
  172. asio::detail::throw_error(ec, "add");
  173. this->service.add(this->implementation, signal_number_2, ec);
  174. asio::detail::throw_error(ec, "add");
  175. this->service.add(this->implementation, signal_number_3, ec);
  176. asio::detail::throw_error(ec, "add");
  177. }
  178. /// Add a signal to a signal_set.
  179. /**
  180. * This function adds the specified signal to the set. It has no effect if the
  181. * signal is already in the set.
  182. *
  183. * @param signal_number The signal to be added to the set.
  184. *
  185. * @throws asio::system_error Thrown on failure.
  186. */
  187. void add(int signal_number)
  188. {
  189. asio::error_code ec;
  190. this->service.add(this->implementation, signal_number, ec);
  191. asio::detail::throw_error(ec, "add");
  192. }
  193. /// Add a signal to a signal_set.
  194. /**
  195. * This function adds the specified signal to the set. It has no effect if the
  196. * signal is already in the set.
  197. *
  198. * @param signal_number The signal to be added to the set.
  199. *
  200. * @param ec Set to indicate what error occurred, if any.
  201. */
  202. asio::error_code add(int signal_number,
  203. asio::error_code& ec)
  204. {
  205. return this->service.add(this->implementation, signal_number, ec);
  206. }
  207. /// Remove a signal from a signal_set.
  208. /**
  209. * This function removes the specified signal from the set. It has no effect
  210. * if the signal is not in the set.
  211. *
  212. * @param signal_number The signal to be removed from the set.
  213. *
  214. * @throws asio::system_error Thrown on failure.
  215. *
  216. * @note Removes any notifications that have been queued for the specified
  217. * signal number.
  218. */
  219. void remove(int signal_number)
  220. {
  221. asio::error_code ec;
  222. this->service.remove(this->implementation, signal_number, ec);
  223. asio::detail::throw_error(ec, "remove");
  224. }
  225. /// Remove a signal from a signal_set.
  226. /**
  227. * This function removes the specified signal from the set. It has no effect
  228. * if the signal is not in the set.
  229. *
  230. * @param signal_number The signal to be removed from the set.
  231. *
  232. * @param ec Set to indicate what error occurred, if any.
  233. *
  234. * @note Removes any notifications that have been queued for the specified
  235. * signal number.
  236. */
  237. asio::error_code remove(int signal_number,
  238. asio::error_code& ec)
  239. {
  240. return this->service.remove(this->implementation, signal_number, ec);
  241. }
  242. /// Remove all signals from a signal_set.
  243. /**
  244. * This function removes all signals from the set. It has no effect if the set
  245. * is already empty.
  246. *
  247. * @throws asio::system_error Thrown on failure.
  248. *
  249. * @note Removes all queued notifications.
  250. */
  251. void clear()
  252. {
  253. asio::error_code ec;
  254. this->service.clear(this->implementation, ec);
  255. asio::detail::throw_error(ec, "clear");
  256. }
  257. /// Remove all signals from a signal_set.
  258. /**
  259. * This function removes all signals from the set. It has no effect if the set
  260. * is already empty.
  261. *
  262. * @param ec Set to indicate what error occurred, if any.
  263. *
  264. * @note Removes all queued notifications.
  265. */
  266. asio::error_code clear(asio::error_code& ec)
  267. {
  268. return this->service.clear(this->implementation, ec);
  269. }
  270. /// Cancel all operations associated with the signal set.
  271. /**
  272. * This function forces the completion of any pending asynchronous wait
  273. * operations against the signal set. The handler for each cancelled
  274. * operation will be invoked with the asio::error::operation_aborted
  275. * error code.
  276. *
  277. * Cancellation does not alter the set of registered signals.
  278. *
  279. * @throws asio::system_error Thrown on failure.
  280. *
  281. * @note If a registered signal occurred before cancel() is called, then the
  282. * handlers for asynchronous wait operations will:
  283. *
  284. * @li have already been invoked; or
  285. *
  286. * @li have been queued for invocation in the near future.
  287. *
  288. * These handlers can no longer be cancelled, and therefore are passed an
  289. * error code that indicates the successful completion of the wait operation.
  290. */
  291. void cancel()
  292. {
  293. asio::error_code ec;
  294. this->service.cancel(this->implementation, ec);
  295. asio::detail::throw_error(ec, "cancel");
  296. }
  297. /// Cancel all operations associated with the signal set.
  298. /**
  299. * This function forces the completion of any pending asynchronous wait
  300. * operations against the signal set. The handler for each cancelled
  301. * operation will be invoked with the asio::error::operation_aborted
  302. * error code.
  303. *
  304. * Cancellation does not alter the set of registered signals.
  305. *
  306. * @param ec Set to indicate what error occurred, if any.
  307. *
  308. * @note If a registered signal occurred before cancel() is called, then the
  309. * handlers for asynchronous wait operations will:
  310. *
  311. * @li have already been invoked; or
  312. *
  313. * @li have been queued for invocation in the near future.
  314. *
  315. * These handlers can no longer be cancelled, and therefore are passed an
  316. * error code that indicates the successful completion of the wait operation.
  317. */
  318. asio::error_code cancel(asio::error_code& ec)
  319. {
  320. return this->service.cancel(this->implementation, ec);
  321. }
  322. /// Start an asynchronous operation to wait for a signal to be delivered.
  323. /**
  324. * This function may be used to initiate an asynchronous wait against the
  325. * signal set. It always returns immediately.
  326. *
  327. * For each call to async_wait(), the supplied handler will be called exactly
  328. * once. The handler will be called when:
  329. *
  330. * @li One of the registered signals in the signal set occurs; or
  331. *
  332. * @li The signal set was cancelled, in which case the handler is passed the
  333. * error code asio::error::operation_aborted.
  334. *
  335. * @param handler The handler to be called when the signal occurs. Copies
  336. * will be made of the handler as required. The function signature of the
  337. * handler must be:
  338. * @code void handler(
  339. * const asio::error_code& error, // Result of operation.
  340. * int signal_number // Indicates which signal occurred.
  341. * ); @endcode
  342. * Regardless of whether the asynchronous operation completes immediately or
  343. * not, the handler will not be invoked from within this function. Invocation
  344. * of the handler will be performed in a manner equivalent to using
  345. * asio::io_service::post().
  346. */
  347. template <typename SignalHandler>
  348. ASIO_INITFN_RESULT_TYPE(SignalHandler,
  349. void (asio::error_code, int))
  350. async_wait(ASIO_MOVE_ARG(SignalHandler) handler)
  351. {
  352. // If you get an error on the following line it means that your handler does
  353. // not meet the documented type requirements for a SignalHandler.
  354. ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
  355. return this->service.async_wait(this->implementation,
  356. ASIO_MOVE_CAST(SignalHandler)(handler));
  357. }
  358. };
  359. } // namespace asio
  360. #include "asio/detail/pop_options.hpp"
  361. #endif // ASIO_BASIC_SIGNAL_SET_HPP