5 // Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_STRAND_HPP
12 #define BOOST_ASIO_STRAND_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/handler_type_requirements.hpp>
20 #include <boost/asio/detail/strand_service.hpp>
21 #include <boost/asio/detail/wrapped_handler.hpp>
22 #include <boost/asio/io_service.hpp>
24 #include <boost/asio/detail/push_options.hpp>
29 /// Provides serialised handler execution.
31 * The io_service::strand class provides the ability to post and dispatch
32 * handlers with the guarantee that none of those handlers will execute
35 * @par Order of handler invocation
38 * @li a strand object @c s
40 * @li an object @c a meeting completion handler requirements
42 * @li an object @c a1 which is an arbitrary copy of @c a made by the
45 * @li an object @c b meeting completion handler requirements
47 * @li an object @c b1 which is an arbitrary copy of @c b made by the
50 * if any of the following conditions are true:
52 * @li @c s.post(a) happens-before @c s.post(b)
54 * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is
55 * performed outside the strand
57 * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is
58 * performed outside the strand
60 * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are
61 * performed outside the strand
63 * then @c asio_handler_invoke(a1, &a1) happens-before
64 * @c asio_handler_invoke(b1, &b1).
66 * Note that in the following case:
67 * @code async_op_1(..., s.wrap(a));
68 * async_op_2(..., s.wrap(b)); @endcode
69 * the completion of the first async operation will perform @c s.dispatch(a),
70 * and the second will perform @c s.dispatch(b), but the order in which those
71 * are performed is unspecified. That is, you cannot state whether one
72 * happens-before the other. Therefore none of the above conditions are met and
73 * no ordering guarantee is made.
76 * @e Distinct @e objects: Safe.@n
77 * @e Shared @e objects: Safe.
82 class io_service::strand
87 * Constructs the strand.
89 * @param io_service The io_service object that the strand will use to
90 * dispatch handlers that are ready to be run.
92 explicit strand(boost::asio::io_service& io_service)
93 : service_(boost::asio::use_service<
94 boost::asio::detail::strand_service>(io_service))
96 service_.construct(impl_);
103 * Handlers posted through the strand that have not yet been invoked will
104 * still be dispatched in a way that meets the guarantee of non-concurrency.
110 /// Get the io_service associated with the strand.
112 * This function may be used to obtain the io_service object that the strand
113 * uses to dispatch handlers for asynchronous operations.
115 * @return A reference to the io_service object that the strand will use to
116 * dispatch handlers. Ownership is not transferred to the caller.
118 boost::asio::io_service& get_io_service()
120 return service_.get_io_service();
123 /// Request the strand to invoke the given handler.
125 * This function is used to ask the strand to execute the given handler.
127 * The strand object guarantees that handlers posted or dispatched through
128 * the strand will not be executed concurrently. The handler may be executed
129 * inside this function if the guarantee can be met. If this function is
130 * called from within a handler that was posted or dispatched through the same
131 * strand, then the new handler will be executed immediately.
133 * The strand's guarantee is in addition to the guarantee provided by the
134 * underlying io_service. The io_service guarantees that the handler will only
135 * be called in a thread in which the io_service's run member function is
136 * currently being invoked.
138 * @param handler The handler to be called. The strand will make a copy of the
139 * handler object as required. The function signature of the handler must be:
140 * @code void handler(); @endcode
142 template <typename CompletionHandler>
143 void dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
145 // If you get an error on the following line it means that your handler does
146 // not meet the documented type requirements for a CompletionHandler.
147 BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
149 service_.dispatch(impl_, BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
152 /// Request the strand to invoke the given handler and return
155 * This function is used to ask the strand to execute the given handler, but
156 * without allowing the strand to call the handler from inside this function.
158 * The strand object guarantees that handlers posted or dispatched through
159 * the strand will not be executed concurrently. The strand's guarantee is in
160 * addition to the guarantee provided by the underlying io_service. The
161 * io_service guarantees that the handler will only be called in a thread in
162 * which the io_service's run member function is currently being invoked.
164 * @param handler The handler to be called. The strand will make a copy of the
165 * handler object as required. The function signature of the handler must be:
166 * @code void handler(); @endcode
168 template <typename CompletionHandler>
169 void post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
171 // If you get an error on the following line it means that your handler does
172 // not meet the documented type requirements for a CompletionHandler.
173 BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
175 service_.post(impl_, BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
178 /// Create a new handler that automatically dispatches the wrapped handler
181 * This function is used to create a new handler function object that, when
182 * invoked, will automatically pass the wrapped handler to the strand's
185 * @param handler The handler to be wrapped. The strand will make a copy of
186 * the handler object as required. The function signature of the handler must
187 * be: @code void handler(A1 a1, ... An an); @endcode
189 * @return A function object that, when invoked, passes the wrapped handler to
190 * the strand's dispatch function. Given a function object with the signature:
191 * @code R f(A1 a1, ... An an); @endcode
192 * If this function object is passed to the wrap function like so:
193 * @code strand.wrap(f); @endcode
194 * then the return value is a function object with the signature
195 * @code void g(A1 a1, ... An an); @endcode
196 * that, when invoked, executes code equivalent to:
197 * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode
199 template <typename Handler>
200 #if defined(GENERATING_DOCUMENTATION)
203 detail::wrapped_handler<strand, Handler>
205 wrap(Handler handler)
207 return detail::wrapped_handler<io_service::strand, Handler>(*this, handler);
211 boost::asio::detail::strand_service& service_;
212 boost::asio::detail::strand_service::implementation_type impl_;
215 /// Typedef for backwards compatibility.
216 typedef boost::asio::io_service::strand strand;
221 #include <boost/asio/detail/pop_options.hpp>
223 #endif // BOOST_ASIO_STRAND_HPP