signal_set.hpp 16 KB

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