annotate DEPENDENCIES/generic/include/boost/asio/strand.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // strand.hpp
Chris@16 3 // ~~~~~~~~~~
Chris@16 4 //
Chris@101 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10
Chris@16 11 #ifndef BOOST_ASIO_STRAND_HPP
Chris@16 12 #define BOOST_ASIO_STRAND_HPP
Chris@16 13
Chris@16 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 15 # pragma once
Chris@16 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 17
Chris@16 18 #include <boost/asio/detail/config.hpp>
Chris@16 19 #include <boost/asio/async_result.hpp>
Chris@16 20 #include <boost/asio/detail/handler_type_requirements.hpp>
Chris@16 21 #include <boost/asio/detail/strand_service.hpp>
Chris@16 22 #include <boost/asio/detail/wrapped_handler.hpp>
Chris@16 23 #include <boost/asio/io_service.hpp>
Chris@16 24
Chris@16 25 #include <boost/asio/detail/push_options.hpp>
Chris@16 26
Chris@16 27 namespace boost {
Chris@16 28 namespace asio {
Chris@16 29
Chris@16 30 /// Provides serialised handler execution.
Chris@16 31 /**
Chris@16 32 * The io_service::strand class provides the ability to post and dispatch
Chris@16 33 * handlers with the guarantee that none of those handlers will execute
Chris@16 34 * concurrently.
Chris@16 35 *
Chris@16 36 * @par Order of handler invocation
Chris@16 37 * Given:
Chris@16 38 *
Chris@16 39 * @li a strand object @c s
Chris@16 40 *
Chris@16 41 * @li an object @c a meeting completion handler requirements
Chris@16 42 *
Chris@16 43 * @li an object @c a1 which is an arbitrary copy of @c a made by the
Chris@16 44 * implementation
Chris@16 45 *
Chris@16 46 * @li an object @c b meeting completion handler requirements
Chris@16 47 *
Chris@16 48 * @li an object @c b1 which is an arbitrary copy of @c b made by the
Chris@16 49 * implementation
Chris@16 50 *
Chris@16 51 * if any of the following conditions are true:
Chris@16 52 *
Chris@16 53 * @li @c s.post(a) happens-before @c s.post(b)
Chris@16 54 *
Chris@16 55 * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is
Chris@16 56 * performed outside the strand
Chris@16 57 *
Chris@16 58 * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is
Chris@16 59 * performed outside the strand
Chris@16 60 *
Chris@16 61 * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are
Chris@16 62 * performed outside the strand
Chris@16 63 *
Chris@16 64 * then @c asio_handler_invoke(a1, &a1) happens-before
Chris@16 65 * @c asio_handler_invoke(b1, &b1).
Chris@16 66 *
Chris@16 67 * Note that in the following case:
Chris@16 68 * @code async_op_1(..., s.wrap(a));
Chris@16 69 * async_op_2(..., s.wrap(b)); @endcode
Chris@16 70 * the completion of the first async operation will perform @c s.dispatch(a),
Chris@16 71 * and the second will perform @c s.dispatch(b), but the order in which those
Chris@16 72 * are performed is unspecified. That is, you cannot state whether one
Chris@16 73 * happens-before the other. Therefore none of the above conditions are met and
Chris@16 74 * no ordering guarantee is made.
Chris@16 75 *
Chris@16 76 * @note The implementation makes no guarantee that handlers posted or
Chris@16 77 * dispatched through different @c strand objects will be invoked concurrently.
Chris@16 78 *
Chris@16 79 * @par Thread Safety
Chris@16 80 * @e Distinct @e objects: Safe.@n
Chris@16 81 * @e Shared @e objects: Safe.
Chris@16 82 *
Chris@16 83 * @par Concepts:
Chris@16 84 * Dispatcher.
Chris@16 85 */
Chris@16 86 class io_service::strand
Chris@16 87 {
Chris@16 88 public:
Chris@16 89 /// Constructor.
Chris@16 90 /**
Chris@16 91 * Constructs the strand.
Chris@16 92 *
Chris@16 93 * @param io_service The io_service object that the strand will use to
Chris@16 94 * dispatch handlers that are ready to be run.
Chris@16 95 */
Chris@16 96 explicit strand(boost::asio::io_service& io_service)
Chris@16 97 : service_(boost::asio::use_service<
Chris@16 98 boost::asio::detail::strand_service>(io_service))
Chris@16 99 {
Chris@16 100 service_.construct(impl_);
Chris@16 101 }
Chris@16 102
Chris@16 103 /// Destructor.
Chris@16 104 /**
Chris@16 105 * Destroys a strand.
Chris@16 106 *
Chris@16 107 * Handlers posted through the strand that have not yet been invoked will
Chris@16 108 * still be dispatched in a way that meets the guarantee of non-concurrency.
Chris@16 109 */
Chris@16 110 ~strand()
Chris@16 111 {
Chris@16 112 }
Chris@16 113
Chris@16 114 /// Get the io_service associated with the strand.
Chris@16 115 /**
Chris@16 116 * This function may be used to obtain the io_service object that the strand
Chris@16 117 * uses to dispatch handlers for asynchronous operations.
Chris@16 118 *
Chris@16 119 * @return A reference to the io_service object that the strand will use to
Chris@16 120 * dispatch handlers. Ownership is not transferred to the caller.
Chris@16 121 */
Chris@16 122 boost::asio::io_service& get_io_service()
Chris@16 123 {
Chris@16 124 return service_.get_io_service();
Chris@16 125 }
Chris@16 126
Chris@16 127 /// Request the strand to invoke the given handler.
Chris@16 128 /**
Chris@16 129 * This function is used to ask the strand to execute the given handler.
Chris@16 130 *
Chris@16 131 * The strand object guarantees that handlers posted or dispatched through
Chris@16 132 * the strand will not be executed concurrently. The handler may be executed
Chris@16 133 * inside this function if the guarantee can be met. If this function is
Chris@16 134 * called from within a handler that was posted or dispatched through the same
Chris@16 135 * strand, then the new handler will be executed immediately.
Chris@16 136 *
Chris@16 137 * The strand's guarantee is in addition to the guarantee provided by the
Chris@16 138 * underlying io_service. The io_service guarantees that the handler will only
Chris@16 139 * be called in a thread in which the io_service's run member function is
Chris@16 140 * currently being invoked.
Chris@16 141 *
Chris@16 142 * @param handler The handler to be called. The strand will make a copy of the
Chris@16 143 * handler object as required. The function signature of the handler must be:
Chris@16 144 * @code void handler(); @endcode
Chris@16 145 */
Chris@16 146 template <typename CompletionHandler>
Chris@16 147 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
Chris@16 148 dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
Chris@16 149 {
Chris@16 150 // If you get an error on the following line it means that your handler does
Chris@16 151 // not meet the documented type requirements for a CompletionHandler.
Chris@16 152 BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
Chris@16 153
Chris@16 154 detail::async_result_init<
Chris@16 155 CompletionHandler, void ()> init(
Chris@16 156 BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
Chris@16 157
Chris@16 158 service_.dispatch(impl_, init.handler);
Chris@16 159
Chris@16 160 return init.result.get();
Chris@16 161 }
Chris@16 162
Chris@16 163 /// Request the strand to invoke the given handler and return
Chris@16 164 /// immediately.
Chris@16 165 /**
Chris@16 166 * This function is used to ask the strand to execute the given handler, but
Chris@16 167 * without allowing the strand to call the handler from inside this function.
Chris@16 168 *
Chris@16 169 * The strand object guarantees that handlers posted or dispatched through
Chris@16 170 * the strand will not be executed concurrently. The strand's guarantee is in
Chris@16 171 * addition to the guarantee provided by the underlying io_service. The
Chris@16 172 * io_service guarantees that the handler will only be called in a thread in
Chris@16 173 * which the io_service's run member function is currently being invoked.
Chris@16 174 *
Chris@16 175 * @param handler The handler to be called. The strand will make a copy of the
Chris@16 176 * handler object as required. The function signature of the handler must be:
Chris@16 177 * @code void handler(); @endcode
Chris@16 178 */
Chris@16 179 template <typename CompletionHandler>
Chris@16 180 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
Chris@16 181 post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
Chris@16 182 {
Chris@16 183 // If you get an error on the following line it means that your handler does
Chris@16 184 // not meet the documented type requirements for a CompletionHandler.
Chris@16 185 BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
Chris@16 186
Chris@16 187 detail::async_result_init<
Chris@16 188 CompletionHandler, void ()> init(
Chris@16 189 BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
Chris@16 190
Chris@16 191 service_.post(impl_, init.handler);
Chris@16 192
Chris@16 193 return init.result.get();
Chris@16 194 }
Chris@16 195
Chris@16 196 /// Create a new handler that automatically dispatches the wrapped handler
Chris@16 197 /// on the strand.
Chris@16 198 /**
Chris@16 199 * This function is used to create a new handler function object that, when
Chris@16 200 * invoked, will automatically pass the wrapped handler to the strand's
Chris@16 201 * dispatch function.
Chris@16 202 *
Chris@16 203 * @param handler The handler to be wrapped. The strand will make a copy of
Chris@16 204 * the handler object as required. The function signature of the handler must
Chris@16 205 * be: @code void handler(A1 a1, ... An an); @endcode
Chris@16 206 *
Chris@16 207 * @return A function object that, when invoked, passes the wrapped handler to
Chris@16 208 * the strand's dispatch function. Given a function object with the signature:
Chris@16 209 * @code R f(A1 a1, ... An an); @endcode
Chris@16 210 * If this function object is passed to the wrap function like so:
Chris@16 211 * @code strand.wrap(f); @endcode
Chris@16 212 * then the return value is a function object with the signature
Chris@16 213 * @code void g(A1 a1, ... An an); @endcode
Chris@16 214 * that, when invoked, executes code equivalent to:
Chris@16 215 * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode
Chris@16 216 */
Chris@16 217 template <typename Handler>
Chris@16 218 #if defined(GENERATING_DOCUMENTATION)
Chris@16 219 unspecified
Chris@16 220 #else
Chris@16 221 detail::wrapped_handler<strand, Handler, detail::is_continuation_if_running>
Chris@16 222 #endif
Chris@16 223 wrap(Handler handler)
Chris@16 224 {
Chris@16 225 return detail::wrapped_handler<io_service::strand, Handler,
Chris@16 226 detail::is_continuation_if_running>(*this, handler);
Chris@16 227 }
Chris@16 228
Chris@16 229 /// Determine whether the strand is running in the current thread.
Chris@16 230 /**
Chris@16 231 * @return @c true if the current thread is executing a handler that was
Chris@16 232 * submitted to the strand using post(), dispatch() or wrap(). Otherwise
Chris@16 233 * returns @c false.
Chris@16 234 */
Chris@16 235 bool running_in_this_thread() const
Chris@16 236 {
Chris@16 237 return service_.running_in_this_thread(impl_);
Chris@16 238 }
Chris@16 239
Chris@16 240 private:
Chris@16 241 boost::asio::detail::strand_service& service_;
Chris@16 242 boost::asio::detail::strand_service::implementation_type impl_;
Chris@16 243 };
Chris@16 244
Chris@101 245 /// (Deprecated: Use boost::asio::io_service::strand.) Typedef for backwards
Chris@101 246 /// compatibility.
Chris@16 247 typedef boost::asio::io_service::strand strand;
Chris@16 248
Chris@16 249 } // namespace asio
Chris@16 250 } // namespace boost
Chris@16 251
Chris@16 252 #include <boost/asio/detail/pop_options.hpp>
Chris@16 253
Chris@16 254 #endif // BOOST_ASIO_STRAND_HPP