basic_signal_set.hpp 13 KB

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