| [/ |
| / Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| / |
| / Distributed under the Boost Software License, Version 1.0. (See accompanying |
| / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| /] |
| |
| [section:asynchronous_operations Requirements on asynchronous operations] |
| |
| In Boost.Asio, an asynchronous operation is initiated by a function that is |
| named with the prefix `async_`. These functions will be referred to as |
| ['initiating functions]. |
| |
| All initiating functions in Boost.Asio take a function object meeting [link |
| boost_asio.reference.Handler handler] requirements as the final parameter. |
| These handlers accept as their first parameter an lvalue of type `const |
| error_code`. |
| |
| Implementations of asynchronous operations in Boost.Asio may call the |
| application programming interface (API) provided by the operating system. If |
| such an operating system API call results in an error, the handler will be |
| invoked with a `const error_code` lvalue that evaluates to true. Otherwise the |
| handler will be invoked with a `const error_code` lvalue that evaluates to |
| false. |
| |
| Unless otherwise noted, when the behaviour of an asynchronous operation is |
| defined "as if" implemented by a __POSIX__ function, the handler will be |
| invoked with a value of type `error_code` that corresponds to the failure |
| condition described by __POSIX__ for that function, if any. Otherwise the |
| handler will be invoked with an implementation-defined `error_code` value that |
| reflects the operating system error. |
| |
| Asynchronous operations will not fail with an error condition that indicates |
| interruption by a signal (__POSIX__ `EINTR`). Asynchronous operations will not |
| fail with any error condition associated with non-blocking operations |
| (__POSIX__ `EWOULDBLOCK`, `EAGAIN` or `EINPROGRESS`; __Windows__ |
| `WSAEWOULDBLOCK` or `WSAEINPROGRESS`). |
| |
| All asynchronous operations have an associated `io_service` object. Where the |
| initiating function is a member function, the associated `io_service` is that |
| returned by the `io_service()` member function on the same object. Where the |
| initiating function is not a member function, the associated `io_service` is |
| that returned by the `io_service()` member function of the first argument to |
| the initiating function. |
| |
| Arguments to initiating functions will be treated as follows: |
| |
| [mdash] If the parameter is declared as a const reference or by-value, the |
| program is not required to guarantee the validity of the argument after the |
| initiating function completes. The implementation may make copies of the |
| argument, and all copies will be destroyed no later than immediately after |
| invocation of the handler. |
| |
| [mdash] If the parameter is declared as a non-const reference, const pointer or |
| non-const pointer, the program must guarantee the validity of the argument |
| until the handler is invoked. |
| |
| The library implementation is only permitted to make calls to an initiating |
| function's arguments' copy constructors or destructors from a thread that |
| satisfies one of the following conditions: |
| |
| [mdash] The thread is executing any member function of the associated |
| `io_service` object. |
| |
| [mdash] The thread is executing the destructor of the associated `io_service` |
| object. |
| |
| [mdash] The thread is executing one of the `io_service` service access |
| functions `use_service`, `add_service` or `has_service`, where the first |
| argument is the associated `io_service` object. |
| |
| [mdash] The thread is executing any member function, constructor or destructor |
| of an object of a class defined in this clause, where the object's |
| `io_service()` member function returns the associated `io_service` object. |
| |
| [mdash] The thread is executing any function defined in this clause, where any |
| argument to the function has an `io_service()` member function that returns the |
| associated `io_service` object. |
| |
| [blurb Boost.Asio may use one or more hidden threads to emulate asynchronous |
| functionality. The above requirements are intended to prevent these hidden |
| threads from making calls to program code. This means that a program can, for |
| example, use thread-unsafe reference counting in handler objects, provided the |
| program ensures that all calls to an `io_service` and related objects occur |
| from the one thread.] |
| |
| The `io_service` object associated with an asynchronous operation will have |
| unfinished work, as if by maintaining the existence of one or more objects of |
| class `io_service::work` constructed using the `io_service`, until immediately |
| after the handler for the asynchronous operation has been invoked. |
| |
| When an asynchronous operation is complete, the handler for the operation will |
| be invoked as if by: |
| |
| # Constructing a bound completion handler `bch` for the handler, as described |
| below. |
| |
| # Calling `ios.post(bch)` to schedule the handler for deferred invocation, |
| where `ios` is the associated `io_service`. |
| |
| This implies that the handler must not be called directly from within |
| the initiating function, even if the asynchronous operation completes |
| immediately. |
| |
| A bound completion handler is a handler object that contains a copy of a |
| user-supplied handler, where the user-supplied handler accepts one or more |
| arguments. The bound completion handler does not accept any arguments, and |
| contains values to be passed as arguments to the user-supplied handler. The |
| bound completion handler forwards the `asio_handler_allocate()`, |
| `asio_handler_deallocate()`, and `asio_handler_invoke()` calls to the |
| corresponding functions for the user-supplied handler. A bound completion |
| handler meets the requirements for a [link |
| boost_asio.reference.CompletionHandler completion handler]. |
| |
| For example, a bound completion handler for a `ReadHandler` may be implemented |
| as follows: |
| |
| template<class ReadHandler> |
| struct bound_read_handler |
| { |
| bound_read_handler(ReadHandler handler, const error_code& ec, size_t s) |
| : handler_(handler), ec_(ec), s_(s) |
| { |
| } |
| |
| void operator()() |
| { |
| handler_(ec_, s_); |
| } |
| |
| ReadHandler handler_; |
| const error_code ec_; |
| const size_t s_; |
| }; |
| |
| template<class ReadHandler> |
| void* asio_handler_allocate(size_t size, |
| bound_read_handler<ReadHandler>* this_handler) |
| { |
| using namespace boost::asio; |
| return asio_handler_allocate(size, &this_handler->handler_); |
| } |
| |
| template<class ReadHandler> |
| void asio_handler_deallocate(void* pointer, std::size_t size, |
| bound_read_handler<ReadHandler>* this_handler) |
| { |
| using namespace boost::asio; |
| asio_handler_deallocate(pointer, size, &this_handler->handler_); |
| } |
| |
| template<class F, class ReadHandler> |
| void asio_handler_invoke(const F& f, |
| bound_read_handler<ReadHandler>* this_handler) |
| { |
| using namespace boost::asio; |
| asio_handler_invoke(f, &this_handler->handler_); |
| } |
| |
| If the thread that initiates an asynchronous operation terminates before the |
| associated handler is invoked, the behaviour is implementation-defined. |
| Specifically, on __Windows__ versions prior to Vista, unfinished operations are |
| cancelled when the initiating thread exits. |
| |
| The handler argument to an initiating function defines a handler identity. That |
| is, the original handler argument and any copies of the handler argument will |
| be considered equivalent. If the implementation needs to allocate storage for |
| an asynchronous operation, the implementation will perform |
| `asio_handler_allocate(size, &h)`, where `size` is the required size in bytes, |
| and `h` is the handler. The implementation will perform |
| `asio_handler_deallocate(p, size, &h)`, where `p` is a pointer to the storage, |
| to deallocate the storage prior to the invocation of the handler via |
| `asio_handler_invoke`. Multiple storage blocks may be allocated for a single |
| asynchronous operation. |
| |
| [endsect] |