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