8 #include <boost/asio/async_result.hpp> 9 #include <boost/asio/detail/config.hpp> 10 #include <boost/assert.hpp> 11 #include <boost/atomic.hpp> 12 #include <boost/intrusive_ptr.hpp> 13 #include <boost/system/error_code.hpp> 14 #include <boost/system/system_error.hpp> 15 #include <boost/throw_exception.hpp> 17 #include <boost/fiber/mutex.hpp> 22 namespace fibers_ext {
25 namespace fbs = ::boost::fibers;
30 enum state_t { init, waiting, complete };
32 typedef fbs::detail::spinlock mutex_t;
33 typedef std::unique_lock<mutex_t> lock_t;
34 typedef boost::intrusive_ptr<yield_completion> ptr_t;
36 std::atomic<std::size_t> use_count_{0};
46 if (complete != state_) {
50 fbs::context::active()->suspend(lk);
55 BOOST_ASSERT(
nullptr != yc);
56 yc->use_count_.fetch_add(1, std::memory_order_relaxed);
60 BOOST_ASSERT(
nullptr != yc);
61 if (1 == yc->use_count_.fetch_sub(1, std::memory_order_release)) {
62 std::atomic_thread_fence(std::memory_order_acquire);
82 ctx_{fbs::context::active()},
87 void operator()(boost::system::error_code
const& ec) {
88 BOOST_ASSERT_MSG(ycomp_,
89 "Must inject yield_completion* " 90 "before calling yield_handler_base::operator()()");
91 BOOST_ASSERT_MSG(yt_.ec_,
92 "Must inject boost::system::error_code* " 93 "before calling yield_handler_base::operator()()");
96 yield_completion::lock_t lk{ycomp_->mtx_};
97 yield_completion::state_t state = ycomp_->state_;
100 ycomp_->state_ = yield_completion::complete;
109 if (yield_completion::waiting == state) {
111 fbs::context::active()->schedule(ctx_);
115 void bind(yield_completion::ptr_t ptr, boost::system::error_code* ec) {
120 ycomp_ = std::move(ptr);
127 boost::fibers::context* ctx_;
131 yield_completion::ptr_t ycomp_{};
143 void(boost::system::error_code, T)>;
150 void operator()(T t) {
152 (*this)(boost::system::error_code(), std::move(t));
156 void operator()(boost::system::error_code
const& ec, T t) {
157 BOOST_ASSERT_MSG(value_,
158 "Must inject value ptr " 159 "before caling yield_handler<T>::operator()()");
162 *value_ = std::move(t);
164 yield_handler_base::operator()(ec);
182 void operator()() { (*this)(boost::system::error_code()); }
185 using yield_handler_base::operator();
201 h.bind(ycomp_, &ec_);
212 boost::throw_exception(boost::system::system_error{ec_});
218 boost::system::error_code ec_{};
219 yield_completion::ptr_t ycomp_;
235 template <
typename T>
236 class async_result<util::fibers_ext::yield_t, void(boost::system::error_code, T)>
240 typedef T return_type;
252 util::fibers_ext::detail::async_result_base::get();
253 return std::move(value_);
257 return_type value_{};
265 class async_result<util::fibers_ext::yield_t, void(boost::system::error_code)>
268 typedef void return_type;