annotate DEPENDENCIES/generic/include/boost/asio/impl/spawn.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 //
Chris@16 2 // impl/spawn.hpp
Chris@16 3 // ~~~~~~~~~~~~~~
Chris@16 4 //
Chris@16 5 // Copyright (c) 2003-2013 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_IMPL_SPAWN_HPP
Chris@16 12 #define BOOST_ASIO_IMPL_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@16 19 #include <boost/asio/async_result.hpp>
Chris@16 20 #include <boost/asio/detail/handler_alloc_helpers.hpp>
Chris@16 21 #include <boost/asio/detail/handler_cont_helpers.hpp>
Chris@16 22 #include <boost/asio/detail/handler_invoke_helpers.hpp>
Chris@16 23 #include <boost/asio/detail/noncopyable.hpp>
Chris@16 24 #include <boost/asio/detail/shared_ptr.hpp>
Chris@16 25 #include <boost/asio/handler_type.hpp>
Chris@16 26
Chris@16 27 #include <boost/asio/detail/push_options.hpp>
Chris@16 28
Chris@16 29 namespace boost {
Chris@16 30 namespace asio {
Chris@16 31 namespace detail {
Chris@16 32
Chris@16 33 template <typename Handler, typename T>
Chris@16 34 class coro_handler
Chris@16 35 {
Chris@16 36 public:
Chris@16 37 coro_handler(basic_yield_context<Handler> ctx)
Chris@16 38 : coro_(ctx.coro_.lock()),
Chris@16 39 ca_(ctx.ca_),
Chris@16 40 handler_(ctx.handler_),
Chris@16 41 ec_(ctx.ec_),
Chris@16 42 value_(0)
Chris@16 43 {
Chris@16 44 }
Chris@16 45
Chris@16 46 void operator()(T value)
Chris@16 47 {
Chris@16 48 *ec_ = boost::system::error_code();
Chris@16 49 *value_ = value;
Chris@16 50 (*coro_)();
Chris@16 51 }
Chris@16 52
Chris@16 53 void operator()(boost::system::error_code ec, T value)
Chris@16 54 {
Chris@16 55 *ec_ = ec;
Chris@16 56 *value_ = value;
Chris@16 57 (*coro_)();
Chris@16 58 }
Chris@16 59
Chris@16 60 //private:
Chris@16 61 shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
Chris@16 62 typename basic_yield_context<Handler>::caller_type& ca_;
Chris@16 63 Handler& handler_;
Chris@16 64 boost::system::error_code* ec_;
Chris@16 65 T* value_;
Chris@16 66 };
Chris@16 67
Chris@16 68 template <typename Handler>
Chris@16 69 class coro_handler<Handler, void>
Chris@16 70 {
Chris@16 71 public:
Chris@16 72 coro_handler(basic_yield_context<Handler> ctx)
Chris@16 73 : coro_(ctx.coro_.lock()),
Chris@16 74 ca_(ctx.ca_),
Chris@16 75 handler_(ctx.handler_),
Chris@16 76 ec_(ctx.ec_)
Chris@16 77 {
Chris@16 78 }
Chris@16 79
Chris@16 80 void operator()()
Chris@16 81 {
Chris@16 82 *ec_ = boost::system::error_code();
Chris@16 83 (*coro_)();
Chris@16 84 }
Chris@16 85
Chris@16 86 void operator()(boost::system::error_code ec)
Chris@16 87 {
Chris@16 88 *ec_ = ec;
Chris@16 89 (*coro_)();
Chris@16 90 }
Chris@16 91
Chris@16 92 //private:
Chris@16 93 shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
Chris@16 94 typename basic_yield_context<Handler>::caller_type& ca_;
Chris@16 95 Handler& handler_;
Chris@16 96 boost::system::error_code* ec_;
Chris@16 97 };
Chris@16 98
Chris@16 99 template <typename Handler, typename T>
Chris@16 100 inline void* asio_handler_allocate(std::size_t size,
Chris@16 101 coro_handler<Handler, T>* this_handler)
Chris@16 102 {
Chris@16 103 return boost_asio_handler_alloc_helpers::allocate(
Chris@16 104 size, this_handler->handler_);
Chris@16 105 }
Chris@16 106
Chris@16 107 template <typename Handler, typename T>
Chris@16 108 inline void asio_handler_deallocate(void* pointer, std::size_t size,
Chris@16 109 coro_handler<Handler, T>* this_handler)
Chris@16 110 {
Chris@16 111 boost_asio_handler_alloc_helpers::deallocate(
Chris@16 112 pointer, size, this_handler->handler_);
Chris@16 113 }
Chris@16 114
Chris@16 115 template <typename Handler, typename T>
Chris@16 116 inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)
Chris@16 117 {
Chris@16 118 return true;
Chris@16 119 }
Chris@16 120
Chris@16 121 template <typename Function, typename Handler, typename T>
Chris@16 122 inline void asio_handler_invoke(Function& function,
Chris@16 123 coro_handler<Handler, T>* this_handler)
Chris@16 124 {
Chris@16 125 boost_asio_handler_invoke_helpers::invoke(
Chris@16 126 function, this_handler->handler_);
Chris@16 127 }
Chris@16 128
Chris@16 129 template <typename Function, typename Handler, typename T>
Chris@16 130 inline void asio_handler_invoke(const Function& function,
Chris@16 131 coro_handler<Handler, T>* this_handler)
Chris@16 132 {
Chris@16 133 boost_asio_handler_invoke_helpers::invoke(
Chris@16 134 function, this_handler->handler_);
Chris@16 135 }
Chris@16 136
Chris@16 137 } // namespace detail
Chris@16 138
Chris@16 139 #if !defined(GENERATING_DOCUMENTATION)
Chris@16 140
Chris@16 141 template <typename Handler, typename ReturnType>
Chris@16 142 struct handler_type<basic_yield_context<Handler>, ReturnType()>
Chris@16 143 {
Chris@16 144 typedef detail::coro_handler<Handler, void> type;
Chris@16 145 };
Chris@16 146
Chris@16 147 template <typename Handler, typename ReturnType, typename Arg1>
Chris@16 148 struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)>
Chris@16 149 {
Chris@16 150 typedef detail::coro_handler<Handler, Arg1> type;
Chris@16 151 };
Chris@16 152
Chris@16 153 template <typename Handler, typename ReturnType>
Chris@16 154 struct handler_type<basic_yield_context<Handler>,
Chris@16 155 ReturnType(boost::system::error_code)>
Chris@16 156 {
Chris@16 157 typedef detail::coro_handler<Handler, void> type;
Chris@16 158 };
Chris@16 159
Chris@16 160 template <typename Handler, typename ReturnType, typename Arg2>
Chris@16 161 struct handler_type<basic_yield_context<Handler>,
Chris@16 162 ReturnType(boost::system::error_code, Arg2)>
Chris@16 163 {
Chris@16 164 typedef detail::coro_handler<Handler, Arg2> type;
Chris@16 165 };
Chris@16 166
Chris@16 167 template <typename Handler, typename T>
Chris@16 168 class async_result<detail::coro_handler<Handler, T> >
Chris@16 169 {
Chris@16 170 public:
Chris@16 171 typedef T type;
Chris@16 172
Chris@16 173 explicit async_result(detail::coro_handler<Handler, T>& h)
Chris@16 174 : ca_(h.ca_)
Chris@16 175 {
Chris@16 176 out_ec_ = h.ec_;
Chris@16 177 if (!out_ec_) h.ec_ = &ec_;
Chris@16 178 h.value_ = &value_;
Chris@16 179 }
Chris@16 180
Chris@16 181 type get()
Chris@16 182 {
Chris@16 183 ca_();
Chris@16 184 if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
Chris@16 185 return value_;
Chris@16 186 }
Chris@16 187
Chris@16 188 private:
Chris@16 189 typename basic_yield_context<Handler>::caller_type& ca_;
Chris@16 190 boost::system::error_code* out_ec_;
Chris@16 191 boost::system::error_code ec_;
Chris@16 192 type value_;
Chris@16 193 };
Chris@16 194
Chris@16 195 template <typename Handler>
Chris@16 196 class async_result<detail::coro_handler<Handler, void> >
Chris@16 197 {
Chris@16 198 public:
Chris@16 199 typedef void type;
Chris@16 200
Chris@16 201 explicit async_result(detail::coro_handler<Handler, void>& h)
Chris@16 202 : ca_(h.ca_)
Chris@16 203 {
Chris@16 204 out_ec_ = h.ec_;
Chris@16 205 if (!out_ec_) h.ec_ = &ec_;
Chris@16 206 }
Chris@16 207
Chris@16 208 void get()
Chris@16 209 {
Chris@16 210 ca_();
Chris@16 211 if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
Chris@16 212 }
Chris@16 213
Chris@16 214 private:
Chris@16 215 typename basic_yield_context<Handler>::caller_type& ca_;
Chris@16 216 boost::system::error_code* out_ec_;
Chris@16 217 boost::system::error_code ec_;
Chris@16 218 };
Chris@16 219
Chris@16 220 namespace detail {
Chris@16 221
Chris@16 222 template <typename Handler, typename Function>
Chris@16 223 struct spawn_data : private noncopyable
Chris@16 224 {
Chris@16 225 spawn_data(BOOST_ASIO_MOVE_ARG(Handler) handler,
Chris@16 226 bool call_handler, BOOST_ASIO_MOVE_ARG(Function) function)
Chris@16 227 : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
Chris@16 228 call_handler_(call_handler),
Chris@16 229 function_(BOOST_ASIO_MOVE_CAST(Function)(function))
Chris@16 230 {
Chris@16 231 }
Chris@16 232
Chris@16 233 weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
Chris@16 234 Handler handler_;
Chris@16 235 bool call_handler_;
Chris@16 236 Function function_;
Chris@16 237 };
Chris@16 238
Chris@16 239 template <typename Handler, typename Function>
Chris@16 240 struct coro_entry_point
Chris@16 241 {
Chris@16 242 void operator()(typename basic_yield_context<Handler>::caller_type& ca)
Chris@16 243 {
Chris@16 244 shared_ptr<spawn_data<Handler, Function> > data(data_);
Chris@16 245 ca(); // Yield until coroutine pointer has been initialised.
Chris@16 246 const basic_yield_context<Handler> yield(
Chris@16 247 data->coro_, ca, data->handler_);
Chris@16 248 (data->function_)(yield);
Chris@16 249 if (data->call_handler_)
Chris@16 250 (data->handler_)();
Chris@16 251 }
Chris@16 252
Chris@16 253 shared_ptr<spawn_data<Handler, Function> > data_;
Chris@16 254 };
Chris@16 255
Chris@16 256 template <typename Handler, typename Function>
Chris@16 257 struct spawn_helper
Chris@16 258 {
Chris@16 259 void operator()()
Chris@16 260 {
Chris@16 261 typedef typename basic_yield_context<Handler>::callee_type callee_type;
Chris@16 262 coro_entry_point<Handler, Function> entry_point = { data_ };
Chris@16 263 shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_));
Chris@16 264 data_->coro_ = coro;
Chris@16 265 (*coro)();
Chris@16 266 }
Chris@16 267
Chris@16 268 shared_ptr<spawn_data<Handler, Function> > data_;
Chris@16 269 boost::coroutines::attributes attributes_;
Chris@16 270 };
Chris@16 271
Chris@16 272 inline void default_spawn_handler() {}
Chris@16 273
Chris@16 274 } // namespace detail
Chris@16 275
Chris@16 276 template <typename Handler, typename Function>
Chris@16 277 void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
Chris@16 278 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 279 const boost::coroutines::attributes& attributes)
Chris@16 280 {
Chris@16 281 detail::spawn_helper<Handler, Function> helper;
Chris@16 282 helper.data_.reset(
Chris@16 283 new detail::spawn_data<Handler, Function>(
Chris@16 284 BOOST_ASIO_MOVE_CAST(Handler)(handler), true,
Chris@16 285 BOOST_ASIO_MOVE_CAST(Function)(function)));
Chris@16 286 helper.attributes_ = attributes;
Chris@16 287 boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
Chris@16 288 }
Chris@16 289
Chris@16 290 template <typename Handler, typename Function>
Chris@16 291 void spawn(basic_yield_context<Handler> ctx,
Chris@16 292 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 293 const boost::coroutines::attributes& attributes)
Chris@16 294 {
Chris@16 295 Handler handler(ctx.handler_); // Explicit copy that might be moved from.
Chris@16 296 detail::spawn_helper<Handler, Function> helper;
Chris@16 297 helper.data_.reset(
Chris@16 298 new detail::spawn_data<Handler, Function>(
Chris@16 299 BOOST_ASIO_MOVE_CAST(Handler)(handler), false,
Chris@16 300 BOOST_ASIO_MOVE_CAST(Function)(function)));
Chris@16 301 helper.attributes_ = attributes;
Chris@16 302 boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
Chris@16 303 }
Chris@16 304
Chris@16 305 template <typename Function>
Chris@16 306 void spawn(boost::asio::io_service::strand strand,
Chris@16 307 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 308 const boost::coroutines::attributes& attributes)
Chris@16 309 {
Chris@16 310 boost::asio::spawn(strand.wrap(&detail::default_spawn_handler),
Chris@16 311 BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
Chris@16 312 }
Chris@16 313
Chris@16 314 template <typename Function>
Chris@16 315 void spawn(boost::asio::io_service& io_service,
Chris@16 316 BOOST_ASIO_MOVE_ARG(Function) function,
Chris@16 317 const boost::coroutines::attributes& attributes)
Chris@16 318 {
Chris@16 319 boost::asio::spawn(boost::asio::io_service::strand(io_service),
Chris@16 320 BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
Chris@16 321 }
Chris@16 322
Chris@16 323 #endif // !defined(GENERATING_DOCUMENTATION)
Chris@16 324
Chris@16 325 } // namespace asio
Chris@16 326 } // namespace boost
Chris@16 327
Chris@16 328 #include <boost/asio/detail/pop_options.hpp>
Chris@16 329
Chris@16 330 #endif // BOOST_ASIO_IMPL_SPAWN_HPP