annotate DEPENDENCIES/generic/include/boost/asio/spawn.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // spawn.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_SPAWN_HPP
Chris@16 12 #define BOOST_ASIO_SPAWN_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@101 19 #include <boost/coroutine/all.hpp>
Chris@16 20 #include <boost/asio/detail/weak_ptr.hpp>
Chris@16 21 #include <boost/asio/detail/wrapped_handler.hpp>
Chris@16 22 #include <boost/asio/io_service.hpp>
Chris@16 23 #include <boost/asio/strand.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 /// Context object the represents the currently executing coroutine.
Chris@16 31 /**
Chris@16 32 * The basic_yield_context class is used to represent the currently executing
Chris@16 33 * stackful coroutine. A basic_yield_context may be passed as a handler to an
Chris@16 34 * asynchronous operation. For example:
Chris@16 35 *
Chris@16 36 * @code template <typename Handler>
Chris@16 37 * void my_coroutine(basic_yield_context<Handler> yield)
Chris@16 38 * {
Chris@16 39 * ...
Chris@16 40 * std::size_t n = my_socket.async_read_some(buffer, yield);
Chris@16 41 * ...
Chris@16 42 * } @endcode
Chris@16 43 *
Chris@16 44 * The initiating function (async_read_some in the above example) suspends the
Chris@16 45 * current coroutine. The coroutine is resumed when the asynchronous operation
Chris@16 46 * completes, and the result of the operation is returned.
Chris@16 47 */
Chris@16 48 template <typename Handler>
Chris@16 49 class basic_yield_context
Chris@16 50 {
Chris@16 51 public:
Chris@16 52 /// The coroutine callee type, used by the implementation.
Chris@16 53 /**
Chris@16 54 * When using Boost.Coroutine v1, this type is:
Chris@16 55 * @code typename coroutine<void()> @endcode
Chris@16 56 * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:
Chris@16 57 * @code push_coroutine<void> @endcode
Chris@16 58 */
Chris@16 59 #if defined(GENERATING_DOCUMENTATION)
Chris@16 60 typedef implementation_defined callee_type;
Chris@101 61 #elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
Chris@16 62 typedef boost::coroutines::push_coroutine<void> callee_type;
Chris@16 63 #else
Chris@16 64 typedef boost::coroutines::coroutine<void()> callee_type;
Chris@16 65 #endif
Chris@16 66
Chris@16 67 /// The coroutine caller type, used by the implementation.
Chris@16 68 /**
Chris@16 69 * When using Boost.Coroutine v1, this type is:
Chris@16 70 * @code typename coroutine<void()>::caller_type @endcode
Chris@16 71 * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:
Chris@16 72 * @code pull_coroutine<void> @endcode
Chris@16 73 */
Chris@16 74 #if defined(GENERATING_DOCUMENTATION)
Chris@16 75 typedef implementation_defined caller_type;
Chris@101 76 #elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)
Chris@16 77 typedef boost::coroutines::pull_coroutine<void> caller_type;
Chris@16 78 #else
Chris@16 79 typedef boost::coroutines::coroutine<void()>::caller_type caller_type;
Chris@16 80 #endif
Chris@16 81
Chris@16 82 /// Construct a yield context to represent the specified coroutine.
Chris@16 83 /**
Chris@16 84 * Most applications do not need to use this constructor. Instead, the
Chris@16 85 * spawn() function passes a yield context as an argument to the coroutine
Chris@16 86 * function.
Chris@16 87 */
Chris@16 88 basic_yield_context(
Chris@16 89 const detail::weak_ptr<callee_type>& coro,
Chris@16 90 caller_type& ca, Handler& handler)
Chris@16 91 : coro_(coro),
Chris@16 92 ca_(ca),
Chris@16 93 handler_(handler),
Chris@16 94 ec_(0)
Chris@16 95 {
Chris@16 96 }
Chris@16 97
Chris@16 98 /// Return a yield context that sets the specified error_code.
Chris@16 99 /**
Chris@16 100 * By default, when a yield context is used with an asynchronous operation, a
Chris@16 101 * non-success error_code is converted to system_error and thrown. This
Chris@16 102 * operator may be used to specify an error_code object that should instead be
Chris@16 103 * set with the asynchronous operation's result. For example:
Chris@16 104 *
Chris@16 105 * @code template <typename Handler>
Chris@16 106 * void my_coroutine(basic_yield_context<Handler> yield)
Chris@16 107 * {
Chris@16 108 * ...
Chris@16 109 * std::size_t n = my_socket.async_read_some(buffer, yield[ec]);
Chris@16 110 * if (ec)
Chris@16 111 * {
Chris@16 112 * // An error occurred.
Chris@16 113 * }
Chris@16 114 * ...
Chris@16 115 * } @endcode
Chris@16 116 */
Chris@16 117 basic_yield_context operator[](boost::system::error_code& ec) const
Chris@16 118 {
Chris@16 119 basic_yield_context tmp(*this);
Chris@16 120 tmp.ec_ = &ec;
Chris@16 121 return tmp;
Chris@16 122 }
Chris@16 123
Chris@16 124 #if defined(GENERATING_DOCUMENTATION)
Chris@16 125 private:
Chris@16 126 #endif // defined(GENERATING_DOCUMENTATION)
Chris@16 127 detail::weak_ptr<callee_type> coro_;
Chris@16 128 caller_type& ca_;
Chris@16 129 Handler& handler_;
Chris@16 130 boost::system::error_code* ec_;
Chris@16 131 };
Chris@16 132
Chris@16 133 #if defined(GENERATING_DOCUMENTATION)
Chris@16 134 /// Context object that represents the currently executing coroutine.
Chris@16 135 typedef basic_yield_context<unspecified> yield_context;
Chris@16 136 #else // defined(GENERATING_DOCUMENTATION)
Chris@16 137 typedef basic_yield_context<
Chris@16 138 detail::wrapped_handler<
Chris@16 139 io_service::strand, void(*)(),
Chris@16 140 detail::is_continuation_if_running> > yield_context;
Chris@16 141 #endif // defined(GENERATING_DOCUMENTATION)
Chris@16 142
Chris@16 143 /**
Chris@16 144 * @defgroup spawn boost::asio::spawn
Chris@16 145 *
Chris@16 146 * @brief Start a new stackful coroutine.
Chris@16 147 *
Chris@16 148 * The spawn() function is a high-level wrapper over the Boost.Coroutine
Chris@16 149 * library. This function enables programs to implement asynchronous logic in a
Chris@16 150 * synchronous manner, as illustrated by the following example:
Chris@16 151 *
Chris@16 152 * @code boost::asio::spawn(my_strand, do_echo);
Chris@16 153 *
Chris@16 154 * // ...
Chris@16 155 *
Chris@16 156 * void do_echo(boost::asio::yield_context yield)
Chris@16 157 * {
Chris@16 158 * try
Chris@16 159 * {
Chris@16 160 * char data[128];
Chris@16 161 * for (;;)
Chris@16 162 * {
Chris@16 163 * std::size_t length =
Chris@16 164 * my_socket.async_read_some(
Chris@16 165 * boost::asio::buffer(data), yield);
Chris@16 166 *
Chris@16 167 * boost::asio::async_write(my_socket,
Chris@16 168 * boost::asio::buffer(data, length), yield);
Chris@16 169 * }
Chris@16 170 * }
Chris@16 171 * catch (std::exception& e)
Chris@16 172 * {
Chris@16 173 * // ...
Chris@16 174 * }
Chris@16 175 * } @endcode
Chris@16 176 */
Chris@16 177 /*@{*/
Chris@16 178
Chris@16 179 /// Start a new stackful coroutine, calling the specified handler when it
Chris@16 180 /// completes.
Chris@16 181 /**
Chris@16 182 * This function is used to launch a new coroutine.
Chris@16 183 *
Chris@16 184 * @param handler A handler to be called when the coroutine exits. More
Chris@16 185 * importantly, the handler provides an execution context (via the the handler
Chris@16 186 * invocation hook) for the coroutine. The handler must have the signature:
Chris@16 187 * @code void handler(); @endcode
Chris@16 188 *
Chris@16 189 * @param function The coroutine function. The function must have the signature:
Chris@16 190 * @code void function(basic_yield_context<Handler> yield); @endcode
Chris@16 191 *
Chris@16 192 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
Chris@16 193 */
Chris@16 194 template <typename Handler, typename Function>
Chris@16 195 void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
Chris@16 196 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 197 const boost::coroutines::attributes& attributes
Chris@16 198 = boost::coroutines::attributes());
Chris@16 199
Chris@16 200 /// Start a new stackful coroutine, inheriting the execution context of another.
Chris@16 201 /**
Chris@16 202 * This function is used to launch a new coroutine.
Chris@16 203 *
Chris@16 204 * @param ctx Identifies the current coroutine as a parent of the new
Chris@16 205 * coroutine. This specifies that the new coroutine should inherit the
Chris@16 206 * execution context of the parent. For example, if the parent coroutine is
Chris@16 207 * executing in a particular strand, then the new coroutine will execute in the
Chris@16 208 * same strand.
Chris@16 209 *
Chris@16 210 * @param function The coroutine function. The function must have the signature:
Chris@16 211 * @code void function(basic_yield_context<Handler> yield); @endcode
Chris@16 212 *
Chris@16 213 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
Chris@16 214 */
Chris@16 215 template <typename Handler, typename Function>
Chris@16 216 void spawn(basic_yield_context<Handler> ctx,
Chris@16 217 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 218 const boost::coroutines::attributes& attributes
Chris@16 219 = boost::coroutines::attributes());
Chris@16 220
Chris@16 221 /// Start a new stackful coroutine that executes in the context of a strand.
Chris@16 222 /**
Chris@16 223 * This function is used to launch a new coroutine.
Chris@16 224 *
Chris@16 225 * @param strand Identifies a strand. By starting multiple coroutines on the
Chris@16 226 * same strand, the implementation ensures that none of those coroutines can
Chris@16 227 * execute simultaneously.
Chris@16 228 *
Chris@16 229 * @param function The coroutine function. The function must have the signature:
Chris@16 230 * @code void function(yield_context yield); @endcode
Chris@16 231 *
Chris@16 232 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
Chris@16 233 */
Chris@16 234 template <typename Function>
Chris@16 235 void spawn(boost::asio::io_service::strand strand,
Chris@16 236 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 237 const boost::coroutines::attributes& attributes
Chris@16 238 = boost::coroutines::attributes());
Chris@16 239
Chris@16 240 /// Start a new stackful coroutine that executes on a given io_service.
Chris@16 241 /**
Chris@16 242 * This function is used to launch a new coroutine.
Chris@16 243 *
Chris@16 244 * @param io_service Identifies the io_service that will run the coroutine. The
Chris@16 245 * new coroutine is implicitly given its own strand within this io_service.
Chris@16 246 *
Chris@16 247 * @param function The coroutine function. The function must have the signature:
Chris@16 248 * @code void function(yield_context yield); @endcode
Chris@16 249 *
Chris@16 250 * @param attributes Boost.Coroutine attributes used to customise the coroutine.
Chris@16 251 */
Chris@16 252 template <typename Function>
Chris@16 253 void spawn(boost::asio::io_service& io_service,
Chris@16 254 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 255 const boost::coroutines::attributes& attributes
Chris@16 256 = boost::coroutines::attributes());
Chris@16 257
Chris@16 258 /*@}*/
Chris@16 259
Chris@16 260 } // namespace asio
Chris@16 261 } // namespace boost
Chris@16 262
Chris@16 263 #include <boost/asio/detail/pop_options.hpp>
Chris@16 264
Chris@16 265 #include <boost/asio/impl/spawn.hpp>
Chris@16 266
Chris@16 267 #endif // BOOST_ASIO_SPAWN_HPP