1 | // |
2 | // io_service.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 | |
11 | #ifndef BOOST_ASIO_IO_SERVICE_HPP |
12 | #define BOOST_ASIO_IO_SERVICE_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <cstddef> |
20 | #include <stdexcept> |
21 | #include <typeinfo> |
22 | #include <boost/asio/async_result.hpp> |
23 | #include <boost/asio/detail/noncopyable.hpp> |
24 | #include <boost/asio/detail/wrapped_handler.hpp> |
25 | #include <boost/system/error_code.hpp> |
26 | |
27 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) |
28 | # include <boost/asio/detail/winsock_init.hpp> |
29 | #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ |
30 | || defined(__osf__) |
31 | # include <boost/asio/detail/signal_init.hpp> |
32 | #endif |
33 | |
34 | #include <boost/asio/detail/push_options.hpp> |
35 | |
36 | namespace boost { |
37 | namespace asio { |
38 | |
39 | class io_service; |
40 | template <typename Service> Service& use_service(io_service& ios); |
41 | template <typename Service> void add_service(io_service& ios, Service* svc); |
42 | template <typename Service> bool has_service(io_service& ios); |
43 | |
44 | namespace detail { |
45 | #if defined(BOOST_ASIO_HAS_IOCP) |
46 | typedef class win_iocp_io_service io_service_impl; |
47 | class win_iocp_overlapped_ptr; |
48 | #else |
49 | typedef class task_io_service io_service_impl; |
50 | #endif |
51 | class service_registry; |
52 | } // namespace detail |
53 | |
54 | /// Provides core I/O functionality. |
55 | /** |
56 | * The io_service class provides the core I/O functionality for users of the |
57 | * asynchronous I/O objects, including: |
58 | * |
59 | * @li boost::asio::ip::tcp::socket |
60 | * @li boost::asio::ip::tcp::acceptor |
61 | * @li boost::asio::ip::udp::socket |
62 | * @li boost::asio::deadline_timer. |
63 | * |
64 | * The io_service class also includes facilities intended for developers of |
65 | * custom asynchronous services. |
66 | * |
67 | * @par Thread Safety |
68 | * @e Distinct @e objects: Safe.@n |
69 | * @e Shared @e objects: Safe, with the specific exceptions of the reset() and |
70 | * notify_fork() functions. Calling reset() while there are unfinished run(), |
71 | * run_one(), poll() or poll_one() calls results in undefined behaviour. The |
72 | * notify_fork() function should not be called while any io_service function, |
73 | * or any function on an I/O object that is associated with the io_service, is |
74 | * being called in another thread. |
75 | * |
76 | * @par Concepts: |
77 | * Dispatcher. |
78 | * |
79 | * @par Synchronous and asynchronous operations |
80 | * |
81 | * Synchronous operations on I/O objects implicitly run the io_service object |
82 | * for an individual operation. The io_service functions run(), run_one(), |
83 | * poll() or poll_one() must be called for the io_service to perform |
84 | * asynchronous operations on behalf of a C++ program. Notification that an |
85 | * asynchronous operation has completed is delivered by invocation of the |
86 | * associated handler. Handlers are invoked only by a thread that is currently |
87 | * calling any overload of run(), run_one(), poll() or poll_one() for the |
88 | * io_service. |
89 | * |
90 | * @par Effect of exceptions thrown from handlers |
91 | * |
92 | * If an exception is thrown from a handler, the exception is allowed to |
93 | * propagate through the throwing thread's invocation of run(), run_one(), |
94 | * poll() or poll_one(). No other threads that are calling any of these |
95 | * functions are affected. It is then the responsibility of the application to |
96 | * catch the exception. |
97 | * |
98 | * After the exception has been caught, the run(), run_one(), poll() or |
99 | * poll_one() call may be restarted @em without the need for an intervening |
100 | * call to reset(). This allows the thread to rejoin the io_service object's |
101 | * thread pool without impacting any other threads in the pool. |
102 | * |
103 | * For example: |
104 | * |
105 | * @code |
106 | * boost::asio::io_service io_service; |
107 | * ... |
108 | * for (;;) |
109 | * { |
110 | * try |
111 | * { |
112 | * io_service.run(); |
113 | * break; // run() exited normally |
114 | * } |
115 | * catch (my_exception& e) |
116 | * { |
117 | * // Deal with exception as appropriate. |
118 | * } |
119 | * } |
120 | * @endcode |
121 | * |
122 | * @par Stopping the io_service from running out of work |
123 | * |
124 | * Some applications may need to prevent an io_service object's run() call from |
125 | * returning when there is no more work to do. For example, the io_service may |
126 | * be being run in a background thread that is launched prior to the |
127 | * application's asynchronous operations. The run() call may be kept running by |
128 | * creating an object of type boost::asio::io_service::work: |
129 | * |
130 | * @code boost::asio::io_service io_service; |
131 | * boost::asio::io_service::work work(io_service); |
132 | * ... @endcode |
133 | * |
134 | * To effect a shutdown, the application will then need to call the io_service |
135 | * object's stop() member function. This will cause the io_service run() call |
136 | * to return as soon as possible, abandoning unfinished operations and without |
137 | * permitting ready handlers to be dispatched. |
138 | * |
139 | * Alternatively, if the application requires that all operations and handlers |
140 | * be allowed to finish normally, the work object may be explicitly destroyed. |
141 | * |
142 | * @code boost::asio::io_service io_service; |
143 | * auto_ptr<boost::asio::io_service::work> work( |
144 | * new boost::asio::io_service::work(io_service)); |
145 | * ... |
146 | * work.reset(); // Allow run() to exit. @endcode |
147 | * |
148 | * @par The io_service class and I/O services |
149 | * |
150 | * Class io_service implements an extensible, type-safe, polymorphic set of I/O |
151 | * services, indexed by service type. An object of class io_service must be |
152 | * initialised before I/O objects such as sockets, resolvers and timers can be |
153 | * used. These I/O objects are distinguished by having constructors that accept |
154 | * an @c io_service& parameter. |
155 | * |
156 | * I/O services exist to manage the logical interface to the operating system on |
157 | * behalf of the I/O objects. In particular, there are resources that are shared |
158 | * across a class of I/O objects. For example, timers may be implemented in |
159 | * terms of a single timer queue. The I/O services manage these shared |
160 | * resources. |
161 | * |
162 | * Access to the services of an io_service is via three function templates, |
163 | * use_service(), add_service() and has_service(). |
164 | * |
165 | * In a call to @c use_service<Service>(), the type argument chooses a service, |
166 | * making available all members of the named type. If @c Service is not present |
167 | * in an io_service, an object of type @c Service is created and added to the |
168 | * io_service. A C++ program can check if an io_service implements a |
169 | * particular service with the function template @c has_service<Service>(). |
170 | * |
171 | * Service objects may be explicitly added to an io_service using the function |
172 | * template @c add_service<Service>(). If the @c Service is already present, the |
173 | * service_already_exists exception is thrown. If the owner of the service is |
174 | * not the same object as the io_service parameter, the invalid_service_owner |
175 | * exception is thrown. |
176 | * |
177 | * Once a service reference is obtained from an io_service object by calling |
178 | * use_service(), that reference remains usable as long as the owning io_service |
179 | * object exists. |
180 | * |
181 | * All I/O service implementations have io_service::service as a public base |
182 | * class. Custom I/O services may be implemented by deriving from this class and |
183 | * then added to an io_service using the facilities described above. |
184 | */ |
185 | class io_service |
186 | : private noncopyable |
187 | { |
188 | private: |
189 | typedef detail::io_service_impl impl_type; |
190 | #if defined(BOOST_ASIO_HAS_IOCP) |
191 | friend class detail::win_iocp_overlapped_ptr; |
192 | #endif |
193 | |
194 | public: |
195 | class work; |
196 | friend class work; |
197 | |
198 | class id; |
199 | |
200 | class service; |
201 | |
202 | class strand; |
203 | |
204 | /// Constructor. |
205 | BOOST_ASIO_DECL io_service(); |
206 | |
207 | /// Constructor. |
208 | /** |
209 | * Construct with a hint about the required level of concurrency. |
210 | * |
211 | * @param concurrency_hint A suggestion to the implementation on how many |
212 | * threads it should allow to run simultaneously. |
213 | */ |
214 | BOOST_ASIO_DECL explicit io_service(std::size_t concurrency_hint); |
215 | |
216 | /// Destructor. |
217 | /** |
218 | * On destruction, the io_service performs the following sequence of |
219 | * operations: |
220 | * |
221 | * @li For each service object @c svc in the io_service set, in reverse order |
222 | * of the beginning of service object lifetime, performs |
223 | * @c svc->shutdown_service(). |
224 | * |
225 | * @li Uninvoked handler objects that were scheduled for deferred invocation |
226 | * on the io_service, or any associated strand, are destroyed. |
227 | * |
228 | * @li For each service object @c svc in the io_service set, in reverse order |
229 | * of the beginning of service object lifetime, performs |
230 | * <tt>delete static_cast<io_service::service*>(svc)</tt>. |
231 | * |
232 | * @note The destruction sequence described above permits programs to |
233 | * simplify their resource management by using @c shared_ptr<>. Where an |
234 | * object's lifetime is tied to the lifetime of a connection (or some other |
235 | * sequence of asynchronous operations), a @c shared_ptr to the object would |
236 | * be bound into the handlers for all asynchronous operations associated with |
237 | * it. This works as follows: |
238 | * |
239 | * @li When a single connection ends, all associated asynchronous operations |
240 | * complete. The corresponding handler objects are destroyed, and all |
241 | * @c shared_ptr references to the objects are destroyed. |
242 | * |
243 | * @li To shut down the whole program, the io_service function stop() is |
244 | * called to terminate any run() calls as soon as possible. The io_service |
245 | * destructor defined above destroys all handlers, causing all @c shared_ptr |
246 | * references to all connection objects to be destroyed. |
247 | */ |
248 | BOOST_ASIO_DECL ~io_service(); |
249 | |
250 | /// Run the io_service object's event processing loop. |
251 | /** |
252 | * The run() function blocks until all work has finished and there are no |
253 | * more handlers to be dispatched, or until the io_service has been stopped. |
254 | * |
255 | * Multiple threads may call the run() function to set up a pool of threads |
256 | * from which the io_service may execute handlers. All threads that are |
257 | * waiting in the pool are equivalent and the io_service may choose any one |
258 | * of them to invoke a handler. |
259 | * |
260 | * A normal exit from the run() function implies that the io_service object |
261 | * is stopped (the stopped() function returns @c true). Subsequent calls to |
262 | * run(), run_one(), poll() or poll_one() will return immediately unless there |
263 | * is a prior call to reset(). |
264 | * |
265 | * @return The number of handlers that were executed. |
266 | * |
267 | * @throws boost::system::system_error Thrown on failure. |
268 | * |
269 | * @note The run() function must not be called from a thread that is currently |
270 | * calling one of run(), run_one(), poll() or poll_one() on the same |
271 | * io_service object. |
272 | * |
273 | * The poll() function may also be used to dispatch ready handlers, but |
274 | * without blocking. |
275 | */ |
276 | BOOST_ASIO_DECL std::size_t run(); |
277 | |
278 | /// Run the io_service object's event processing loop. |
279 | /** |
280 | * The run() function blocks until all work has finished and there are no |
281 | * more handlers to be dispatched, or until the io_service has been stopped. |
282 | * |
283 | * Multiple threads may call the run() function to set up a pool of threads |
284 | * from which the io_service may execute handlers. All threads that are |
285 | * waiting in the pool are equivalent and the io_service may choose any one |
286 | * of them to invoke a handler. |
287 | * |
288 | * A normal exit from the run() function implies that the io_service object |
289 | * is stopped (the stopped() function returns @c true). Subsequent calls to |
290 | * run(), run_one(), poll() or poll_one() will return immediately unless there |
291 | * is a prior call to reset(). |
292 | * |
293 | * @param ec Set to indicate what error occurred, if any. |
294 | * |
295 | * @return The number of handlers that were executed. |
296 | * |
297 | * @note The run() function must not be called from a thread that is currently |
298 | * calling one of run(), run_one(), poll() or poll_one() on the same |
299 | * io_service object. |
300 | * |
301 | * The poll() function may also be used to dispatch ready handlers, but |
302 | * without blocking. |
303 | */ |
304 | BOOST_ASIO_DECL std::size_t run(boost::system::error_code& ec); |
305 | |
306 | /// Run the io_service object's event processing loop to execute at most one |
307 | /// handler. |
308 | /** |
309 | * The run_one() function blocks until one handler has been dispatched, or |
310 | * until the io_service has been stopped. |
311 | * |
312 | * @return The number of handlers that were executed. A zero return value |
313 | * implies that the io_service object is stopped (the stopped() function |
314 | * returns @c true). Subsequent calls to run(), run_one(), poll() or |
315 | * poll_one() will return immediately unless there is a prior call to |
316 | * reset(). |
317 | * |
318 | * @throws boost::system::system_error Thrown on failure. |
319 | */ |
320 | BOOST_ASIO_DECL std::size_t run_one(); |
321 | |
322 | /// Run the io_service object's event processing loop to execute at most one |
323 | /// handler. |
324 | /** |
325 | * The run_one() function blocks until one handler has been dispatched, or |
326 | * until the io_service has been stopped. |
327 | * |
328 | * @return The number of handlers that were executed. A zero return value |
329 | * implies that the io_service object is stopped (the stopped() function |
330 | * returns @c true). Subsequent calls to run(), run_one(), poll() or |
331 | * poll_one() will return immediately unless there is a prior call to |
332 | * reset(). |
333 | * |
334 | * @return The number of handlers that were executed. |
335 | */ |
336 | BOOST_ASIO_DECL std::size_t run_one(boost::system::error_code& ec); |
337 | |
338 | /// Run the io_service object's event processing loop to execute ready |
339 | /// handlers. |
340 | /** |
341 | * The poll() function runs handlers that are ready to run, without blocking, |
342 | * until the io_service has been stopped or there are no more ready handlers. |
343 | * |
344 | * @return The number of handlers that were executed. |
345 | * |
346 | * @throws boost::system::system_error Thrown on failure. |
347 | */ |
348 | BOOST_ASIO_DECL std::size_t poll(); |
349 | |
350 | /// Run the io_service object's event processing loop to execute ready |
351 | /// handlers. |
352 | /** |
353 | * The poll() function runs handlers that are ready to run, without blocking, |
354 | * until the io_service has been stopped or there are no more ready handlers. |
355 | * |
356 | * @param ec Set to indicate what error occurred, if any. |
357 | * |
358 | * @return The number of handlers that were executed. |
359 | */ |
360 | BOOST_ASIO_DECL std::size_t poll(boost::system::error_code& ec); |
361 | |
362 | /// Run the io_service object's event processing loop to execute one ready |
363 | /// handler. |
364 | /** |
365 | * The poll_one() function runs at most one handler that is ready to run, |
366 | * without blocking. |
367 | * |
368 | * @return The number of handlers that were executed. |
369 | * |
370 | * @throws boost::system::system_error Thrown on failure. |
371 | */ |
372 | BOOST_ASIO_DECL std::size_t poll_one(); |
373 | |
374 | /// Run the io_service object's event processing loop to execute one ready |
375 | /// handler. |
376 | /** |
377 | * The poll_one() function runs at most one handler that is ready to run, |
378 | * without blocking. |
379 | * |
380 | * @param ec Set to indicate what error occurred, if any. |
381 | * |
382 | * @return The number of handlers that were executed. |
383 | */ |
384 | BOOST_ASIO_DECL std::size_t poll_one(boost::system::error_code& ec); |
385 | |
386 | /// Stop the io_service object's event processing loop. |
387 | /** |
388 | * This function does not block, but instead simply signals the io_service to |
389 | * stop. All invocations of its run() or run_one() member functions should |
390 | * return as soon as possible. Subsequent calls to run(), run_one(), poll() |
391 | * or poll_one() will return immediately until reset() is called. |
392 | */ |
393 | BOOST_ASIO_DECL void stop(); |
394 | |
395 | /// Determine whether the io_service object has been stopped. |
396 | /** |
397 | * This function is used to determine whether an io_service object has been |
398 | * stopped, either through an explicit call to stop(), or due to running out |
399 | * of work. When an io_service object is stopped, calls to run(), run_one(), |
400 | * poll() or poll_one() will return immediately without invoking any |
401 | * handlers. |
402 | * |
403 | * @return @c true if the io_service object is stopped, otherwise @c false. |
404 | */ |
405 | BOOST_ASIO_DECL bool stopped() const; |
406 | |
407 | /// Reset the io_service in preparation for a subsequent run() invocation. |
408 | /** |
409 | * This function must be called prior to any second or later set of |
410 | * invocations of the run(), run_one(), poll() or poll_one() functions when a |
411 | * previous invocation of these functions returned due to the io_service |
412 | * being stopped or running out of work. After a call to reset(), the |
413 | * io_service object's stopped() function will return @c false. |
414 | * |
415 | * This function must not be called while there are any unfinished calls to |
416 | * the run(), run_one(), poll() or poll_one() functions. |
417 | */ |
418 | BOOST_ASIO_DECL void reset(); |
419 | |
420 | /// Request the io_service to invoke the given handler. |
421 | /** |
422 | * This function is used to ask the io_service to execute the given handler. |
423 | * |
424 | * The io_service guarantees that the handler will only be called in a thread |
425 | * in which the run(), run_one(), poll() or poll_one() member functions is |
426 | * currently being invoked. The handler may be executed inside this function |
427 | * if the guarantee can be met. |
428 | * |
429 | * @param handler The handler to be called. The io_service will make |
430 | * a copy of the handler object as required. The function signature of the |
431 | * handler must be: @code void handler(); @endcode |
432 | * |
433 | * @note This function throws an exception only if: |
434 | * |
435 | * @li the handler's @c asio_handler_allocate function; or |
436 | * |
437 | * @li the handler's copy constructor |
438 | * |
439 | * throws an exception. |
440 | */ |
441 | template <typename CompletionHandler> |
442 | BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) |
443 | dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler); |
444 | |
445 | /// Request the io_service to invoke the given handler and return immediately. |
446 | /** |
447 | * This function is used to ask the io_service to execute the given handler, |
448 | * but without allowing the io_service to call the handler from inside this |
449 | * function. |
450 | * |
451 | * The io_service guarantees that the handler will only be called in a thread |
452 | * in which the run(), run_one(), poll() or poll_one() member functions is |
453 | * currently being invoked. |
454 | * |
455 | * @param handler The handler to be called. The io_service will make |
456 | * a copy of the handler object as required. The function signature of the |
457 | * handler must be: @code void handler(); @endcode |
458 | * |
459 | * @note This function throws an exception only if: |
460 | * |
461 | * @li the handler's @c asio_handler_allocate function; or |
462 | * |
463 | * @li the handler's copy constructor |
464 | * |
465 | * throws an exception. |
466 | */ |
467 | template <typename CompletionHandler> |
468 | BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) |
469 | post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler); |
470 | |
471 | /// Create a new handler that automatically dispatches the wrapped handler |
472 | /// on the io_service. |
473 | /** |
474 | * This function is used to create a new handler function object that, when |
475 | * invoked, will automatically pass the wrapped handler to the io_service |
476 | * object's dispatch function. |
477 | * |
478 | * @param handler The handler to be wrapped. The io_service will make a copy |
479 | * of the handler object as required. The function signature of the handler |
480 | * must be: @code void handler(A1 a1, ... An an); @endcode |
481 | * |
482 | * @return A function object that, when invoked, passes the wrapped handler to |
483 | * the io_service object's dispatch function. Given a function object with the |
484 | * signature: |
485 | * @code R f(A1 a1, ... An an); @endcode |
486 | * If this function object is passed to the wrap function like so: |
487 | * @code io_service.wrap(f); @endcode |
488 | * then the return value is a function object with the signature |
489 | * @code void g(A1 a1, ... An an); @endcode |
490 | * that, when invoked, executes code equivalent to: |
491 | * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode |
492 | */ |
493 | template <typename Handler> |
494 | #if defined(GENERATING_DOCUMENTATION) |
495 | unspecified |
496 | #else |
497 | detail::wrapped_handler<io_service&, Handler> |
498 | #endif |
499 | wrap(Handler handler); |
500 | |
501 | /// Fork-related event notifications. |
502 | enum fork_event |
503 | { |
504 | /// Notify the io_service that the process is about to fork. |
505 | fork_prepare, |
506 | |
507 | /// Notify the io_service that the process has forked and is the parent. |
508 | fork_parent, |
509 | |
510 | /// Notify the io_service that the process has forked and is the child. |
511 | fork_child |
512 | }; |
513 | |
514 | /// Notify the io_service of a fork-related event. |
515 | /** |
516 | * This function is used to inform the io_service that the process is about |
517 | * to fork, or has just forked. This allows the io_service, and the services |
518 | * it contains, to perform any necessary housekeeping to ensure correct |
519 | * operation following a fork. |
520 | * |
521 | * This function must not be called while any other io_service function, or |
522 | * any function on an I/O object associated with the io_service, is being |
523 | * called in another thread. It is, however, safe to call this function from |
524 | * within a completion handler, provided no other thread is accessing the |
525 | * io_service. |
526 | * |
527 | * @param event A fork-related event. |
528 | * |
529 | * @throws boost::system::system_error Thrown on failure. If the notification |
530 | * fails the io_service object should no longer be used and should be |
531 | * destroyed. |
532 | * |
533 | * @par Example |
534 | * The following code illustrates how to incorporate the notify_fork() |
535 | * function: |
536 | * @code my_io_service.notify_fork(boost::asio::io_service::fork_prepare); |
537 | * if (fork() == 0) |
538 | * { |
539 | * // This is the child process. |
540 | * my_io_service.notify_fork(boost::asio::io_service::fork_child); |
541 | * } |
542 | * else |
543 | * { |
544 | * // This is the parent process. |
545 | * my_io_service.notify_fork(boost::asio::io_service::fork_parent); |
546 | * } @endcode |
547 | * |
548 | * @note For each service object @c svc in the io_service set, performs |
549 | * <tt>svc->fork_service();</tt>. When processing the fork_prepare event, |
550 | * services are visited in reverse order of the beginning of service object |
551 | * lifetime. Otherwise, services are visited in order of the beginning of |
552 | * service object lifetime. |
553 | */ |
554 | BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event event); |
555 | |
556 | /// Obtain the service object corresponding to the given type. |
557 | /** |
558 | * This function is used to locate a service object that corresponds to |
559 | * the given service type. If there is no existing implementation of the |
560 | * service, then the io_service will create a new instance of the service. |
561 | * |
562 | * @param ios The io_service object that owns the service. |
563 | * |
564 | * @return The service interface implementing the specified service type. |
565 | * Ownership of the service interface is not transferred to the caller. |
566 | */ |
567 | template <typename Service> |
568 | friend Service& use_service(io_service& ios); |
569 | |
570 | /// Add a service object to the io_service. |
571 | /** |
572 | * This function is used to add a service to the io_service. |
573 | * |
574 | * @param ios The io_service object that owns the service. |
575 | * |
576 | * @param svc The service object. On success, ownership of the service object |
577 | * is transferred to the io_service. When the io_service object is destroyed, |
578 | * it will destroy the service object by performing: |
579 | * @code delete static_cast<io_service::service*>(svc) @endcode |
580 | * |
581 | * @throws boost::asio::service_already_exists Thrown if a service of the |
582 | * given type is already present in the io_service. |
583 | * |
584 | * @throws boost::asio::invalid_service_owner Thrown if the service's owning |
585 | * io_service is not the io_service object specified by the ios parameter. |
586 | */ |
587 | template <typename Service> |
588 | friend void add_service(io_service& ios, Service* svc); |
589 | |
590 | /// Determine if an io_service contains a specified service type. |
591 | /** |
592 | * This function is used to determine whether the io_service contains a |
593 | * service object corresponding to the given service type. |
594 | * |
595 | * @param ios The io_service object that owns the service. |
596 | * |
597 | * @return A boolean indicating whether the io_service contains the service. |
598 | */ |
599 | template <typename Service> |
600 | friend bool has_service(io_service& ios); |
601 | |
602 | private: |
603 | #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) |
604 | detail::winsock_init<> init_; |
605 | #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ |
606 | || defined(__osf__) |
607 | detail::signal_init<> init_; |
608 | #endif |
609 | |
610 | // The service registry. |
611 | boost::asio::detail::service_registry* service_registry_; |
612 | |
613 | // The implementation. |
614 | impl_type& impl_; |
615 | }; |
616 | |
617 | /// Class to inform the io_service when it has work to do. |
618 | /** |
619 | * The work class is used to inform the io_service when work starts and |
620 | * finishes. This ensures that the io_service object's run() function will not |
621 | * exit while work is underway, and that it does exit when there is no |
622 | * unfinished work remaining. |
623 | * |
624 | * The work class is copy-constructible so that it may be used as a data member |
625 | * in a handler class. It is not assignable. |
626 | */ |
627 | class io_service::work |
628 | { |
629 | public: |
630 | /// Constructor notifies the io_service that work is starting. |
631 | /** |
632 | * The constructor is used to inform the io_service that some work has begun. |
633 | * This ensures that the io_service object's run() function will not exit |
634 | * while the work is underway. |
635 | */ |
636 | explicit work(boost::asio::io_service& io_service); |
637 | |
638 | /// Copy constructor notifies the io_service that work is starting. |
639 | /** |
640 | * The constructor is used to inform the io_service that some work has begun. |
641 | * This ensures that the io_service object's run() function will not exit |
642 | * while the work is underway. |
643 | */ |
644 | work(const work& other); |
645 | |
646 | /// Destructor notifies the io_service that the work is complete. |
647 | /** |
648 | * The destructor is used to inform the io_service that some work has |
649 | * finished. Once the count of unfinished work reaches zero, the io_service |
650 | * object's run() function is permitted to exit. |
651 | */ |
652 | ~work(); |
653 | |
654 | /// Get the io_service associated with the work. |
655 | boost::asio::io_service& get_io_service(); |
656 | |
657 | private: |
658 | // Prevent assignment. |
659 | void operator=(const work& other); |
660 | |
661 | // The io_service implementation. |
662 | detail::io_service_impl& io_service_impl_; |
663 | }; |
664 | |
665 | /// Class used to uniquely identify a service. |
666 | class io_service::id |
667 | : private noncopyable |
668 | { |
669 | public: |
670 | /// Constructor. |
671 | id() {} |
672 | }; |
673 | |
674 | /// Base class for all io_service services. |
675 | class io_service::service |
676 | : private noncopyable |
677 | { |
678 | public: |
679 | /// Get the io_service object that owns the service. |
680 | boost::asio::io_service& get_io_service(); |
681 | |
682 | protected: |
683 | /// Constructor. |
684 | /** |
685 | * @param owner The io_service object that owns the service. |
686 | */ |
687 | BOOST_ASIO_DECL service(boost::asio::io_service& owner); |
688 | |
689 | /// Destructor. |
690 | BOOST_ASIO_DECL virtual ~service(); |
691 | |
692 | private: |
693 | /// Destroy all user-defined handler objects owned by the service. |
694 | virtual void shutdown_service() = 0; |
695 | |
696 | /// Handle notification of a fork-related event to perform any necessary |
697 | /// housekeeping. |
698 | /** |
699 | * This function is not a pure virtual so that services only have to |
700 | * implement it if necessary. The default implementation does nothing. |
701 | */ |
702 | BOOST_ASIO_DECL virtual void fork_service( |
703 | boost::asio::io_service::fork_event event); |
704 | |
705 | friend class boost::asio::detail::service_registry; |
706 | struct key |
707 | { |
708 | key() : type_info_(0), id_(0) {} |
709 | const std::type_info* type_info_; |
710 | const boost::asio::io_service::id* id_; |
711 | } key_; |
712 | |
713 | boost::asio::io_service& owner_; |
714 | service* next_; |
715 | }; |
716 | |
717 | /// Exception thrown when trying to add a duplicate service to an io_service. |
718 | class service_already_exists |
719 | : public std::logic_error |
720 | { |
721 | public: |
722 | BOOST_ASIO_DECL service_already_exists(); |
723 | }; |
724 | |
725 | /// Exception thrown when trying to add a service object to an io_service where |
726 | /// the service has a different owner. |
727 | class invalid_service_owner |
728 | : public std::logic_error |
729 | { |
730 | public: |
731 | BOOST_ASIO_DECL invalid_service_owner(); |
732 | }; |
733 | |
734 | namespace detail { |
735 | |
736 | // Special derived service id type to keep classes header-file only. |
737 | template <typename Type> |
738 | class service_id |
739 | : public boost::asio::io_service::id |
740 | { |
741 | }; |
742 | |
743 | // Special service base class to keep classes header-file only. |
744 | template <typename Type> |
745 | class service_base |
746 | : public boost::asio::io_service::service |
747 | { |
748 | public: |
749 | static boost::asio::detail::service_id<Type> id; |
750 | |
751 | // Constructor. |
752 | service_base(boost::asio::io_service& io_service) |
753 | : boost::asio::io_service::service(io_service) |
754 | { |
755 | } |
756 | }; |
757 | |
758 | template <typename Type> |
759 | boost::asio::detail::service_id<Type> service_base<Type>::id; |
760 | |
761 | } // namespace detail |
762 | } // namespace asio |
763 | } // namespace boost |
764 | |
765 | #include <boost/asio/detail/pop_options.hpp> |
766 | |
767 | #include <boost/asio/impl/io_service.hpp> |
768 | #if defined(BOOST_ASIO_HEADER_ONLY) |
769 | # include <boost/asio/impl/io_service.ipp> |
770 | #endif // defined(BOOST_ASIO_HEADER_ONLY) |
771 | |
772 | #endif // BOOST_ASIO_IO_SERVICE_HPP |
773 | |