From 51f4cb1a26bbc5ada7d86ad2aeea164dfb1210c9 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Fri, 29 Jan 2016 17:04:15 +0100 Subject: [PATCH] update asio integration in directory examples --- examples/Jamfile.v2 | 3 +- examples/asio/detail/promise_handler.hpp | 15 +- examples/asio/detail/spawn.hpp | 314 ----------------------- examples/asio/echo_server.cpp | 123 +++++++++ examples/asio/echo_server_spawn.cpp | 108 -------- examples/asio/echo_server_yield.cpp | 91 ------- examples/asio/ps/server.cpp | 3 +- examples/asio/round_robin.hpp | 52 ++-- examples/asio/spawn.hpp | 85 ------ 9 files changed, 151 insertions(+), 643 deletions(-) delete mode 100644 examples/asio/detail/spawn.hpp create mode 100644 examples/asio/echo_server.cpp delete mode 100644 examples/asio/echo_server_spawn.cpp delete mode 100644 examples/asio/echo_server_yield.cpp delete mode 100644 examples/asio/spawn.hpp diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 index 44ef72fe..57df9f9c 100644 --- a/examples/Jamfile.v2 +++ b/examples/Jamfile.v2 @@ -40,8 +40,7 @@ exe work_sharing : work_sharing.cpp ; exe work_stealing : work_stealing.cpp ; exe asio/echo_client : asio/echo_client.cpp ; -exe asio/echo_server_spawn : asio/echo_server_spawn.cpp ; -exe asio/echo_server_yield : asio/echo_server_yield.cpp ; +exe asio/echo_server : asio/echo_server.cpp ; exe asio/ps/publisher : asio/ps/publisher.cpp ; exe asio/ps/server : asio/ps/server.cpp ; exe asio/ps/subscriber : asio/ps/subscriber.cpp ; diff --git a/examples/asio/detail/promise_handler.hpp b/examples/asio/detail/promise_handler.hpp index 4f612178..fd24e3aa 100644 --- a/examples/asio/detail/promise_handler.hpp +++ b/examples/asio/detail/promise_handler.hpp @@ -107,6 +107,7 @@ public: } //-> void operator()( boost::system::error_code const& ec, T t) { + get_promise()->set_value( t); if ( should_set_value( ec) ) { get_promise()->set_value( t); } @@ -145,25 +146,23 @@ public: using promise_handler_base< void >::get_promise; }; -}}} - -namespace asio { -namespace detail { - // Specialize asio_handler_invoke hook to ensure that any exceptions thrown // from the handler are propagated back to the caller via the future. template< typename Function, typename T > -void asio_handler_invoke( Function f, fibers::asio::detail::promise_handler< T > * h) { - typename fibers::asio::detail::promise_handler< T >::promise_ptr +void asio_handler_invoke( Function f, promise_handler< T > * h) { + typename promise_handler< T >::promise_ptr p( h->get_promise() ); try { + fprintf(stderr, "before f()\n"); f(); + fprintf(stderr, "after f()\n"); } catch (...) { + fprintf(stderr, "p->set_exception()\n"); p->set_exception( std::current_exception() ); } } -}}} +}}}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX diff --git a/examples/asio/detail/spawn.hpp b/examples/asio/detail/spawn.hpp deleted file mode 100644 index 18f92718..00000000 --- a/examples/asio/detail/spawn.hpp +++ /dev/null @@ -1,314 +0,0 @@ -// -// detail/spawn.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_FIBERS_ASIO_DETAIL_SPAWN_HPP -#define BOOST_FIBERS_ASIO_DETAIL_SPAWN_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace asio { -namespace detail { - -template< typename Handler, typename T > -class fiber_handler { -public: - fiber_handler( basic_yield_context< Handler > ctx) : - ctx_( ctx.ctx_), - handler_( ctx.handler_), - ec_( ctx.ec_), - value_( 0) { - } - - void operator()( T value) { - * ec_ = boost::system::error_code(); - * value_ = value; - boost::fibers::context::active()->set_ready( ctx_); - } - - void operator()( boost::system::error_code ec, T value) { - * ec_ = ec; - * value_ = value; - boost::fibers::context::active()->set_ready( ctx_); - } - -//private: - boost::fibers::context * ctx_; - Handler & handler_; - boost::system::error_code * ec_; - T * value_; -}; - -template< typename Handler > -class fiber_handler< Handler, void > { -public: - fiber_handler( basic_yield_context< Handler > ctx) : - ctx_( ctx.ctx_), - handler_( ctx.handler_), - ec_( ctx.ec_) { - } - - void operator()() { - * ec_ = boost::system::error_code(); - boost::fibers::context::active()->set_ready( ctx_); - } - - void operator()( boost::system::error_code ec) { - * ec_ = ec; - boost::fibers::context::active()->set_ready( ctx_); - } - -//private: - boost::fibers::context * ctx_; - Handler & handler_; - boost::system::error_code * ec_; -}; - -template< typename Handler, typename T > -void* asio_handler_allocate( std::size_t size, - fiber_handler< Handler, T > * this_handler) { - return boost_asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -} - -template< typename Handler, typename T > -void asio_handler_deallocate( void* pointer, std::size_t size, - fiber_handler< Handler, T > * this_handler) { - boost_asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -} - -template< typename Handler, typename T > -bool asio_handler_is_continuation( fiber_handler *) { - return true; -} - -template< typename Function, typename Handler, typename T > -void asio_handler_invoke( Function & function, - fiber_handler< Handler, T > * this_handler) { - boost_asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -} - -template< typename Function, typename Handler, typename T > -void asio_handler_invoke( Function const& function, - fiber_handler< Handler, T > * this_handler) { - boost_asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -} - -}}} - -namespace asio { - -template< typename Handler, typename ReturnType > -struct handler_type< - boost::fibers::asio::basic_yield_context< Handler >, - ReturnType() -> -{ typedef boost::fibers::asio::detail::fiber_handler< Handler, void > type; }; - -template< typename Handler, typename ReturnType, typename Arg1 > -struct handler_type< - boost::fibers::asio::basic_yield_context< Handler >, - ReturnType( Arg1) -> -{ typedef boost::fibers::asio::detail::fiber_handler< Handler, Arg1 > type; }; - -template< typename Handler, typename ReturnType > -struct handler_type< - boost::fibers::asio::basic_yield_context< Handler >, - ReturnType( boost::system::error_code) -> -{ typedef boost::fibers::asio::detail::fiber_handler type; }; - -template< typename Handler, typename ReturnType, typename Arg2 > -struct handler_type< - boost::fibers::asio::basic_yield_context< Handler >, - ReturnType( boost::system::error_code, Arg2) -> -{ typedef boost::fibers::asio::detail::fiber_handler< Handler, Arg2 > type; }; - -template< typename Handler, typename T > -class async_result< boost::fibers::asio::detail::fiber_handler< Handler, T > > { -public: - typedef T type; - - explicit async_result( boost::fibers::asio::detail::fiber_handler< Handler, T > & h) : - out_ec_( nullptr), ec_(), value_() { - out_ec_ = h.ec_; - if ( ! out_ec_) { - h.ec_ = & ec_; - } - h.value_ = & value_; - } - - type get() { - boost::fibers::context::active()->suspend(); - if ( ! out_ec_ && ec_) { - throw boost::system::system_error( ec_); - } - return value_; - } - -private: - boost::system::error_code * out_ec_; - boost::system::error_code ec_; - type value_; -}; - -template< typename Handler > -class async_result< boost::fibers::asio::detail::fiber_handler< Handler, void > > { -public: - typedef void type; - - explicit async_result( boost::fibers::asio::detail::fiber_handler< Handler, void > & h) : - out_ec_( nullptr), ec_() { - out_ec_ = h.ec_; - if ( ! out_ec_) { - h.ec_ = &ec_; - } - } - - void get() { - boost::fibers::context::active()->suspend(); - if ( ! out_ec_ && ec_) { - throw boost::system::system_error( ec_); - } - } - -private: - boost::system::error_code * out_ec_; - boost::system::error_code ec_; -}; - -} - -namespace fibers { -namespace asio { -namespace detail { - -template< typename Handler, typename Function > -struct spawn_data : private noncopyable { - spawn_data( boost::asio::io_service& io_svc, BOOST_ASIO_MOVE_ARG( Handler) handler, - bool call_handler, BOOST_ASIO_MOVE_ARG( Function) function) : - io_svc_(io_svc), - handler_( BOOST_ASIO_MOVE_CAST( Handler)( handler) ), - call_handler_( call_handler), - function_( BOOST_ASIO_MOVE_CAST( Function)( function) ) { - } - - boost::asio::io_service & io_svc_; - boost::fibers::context * ctx_; - Handler handler_; - bool call_handler_; - Function function_; -}; - -template< typename Handler, typename Function > -struct fiber_entry_point { - void operator()() { - shared_ptr< spawn_data< Handler, Function > > data( data_); - data->ctx_ = boost::fibers::context::active(); - const basic_yield_context< Handler > yield( - data->ctx_, data->handler_); - - boost::asio::io_service::work w( data->io_svc_); - ( data->function_)( yield); - if ( data->call_handler_) { - ( data->handler_)(); - } - } - - shared_ptr< spawn_data< Handler, Function > > data_; -}; - -template< typename Handler, typename Function > -struct spawn_helper { - void operator()() { - fiber_entry_point< Handler, Function > entry_point = { data_ }; - boost::fibers::fiber( entry_point).detach(); - boost::this_fiber::yield(); - } - - shared_ptr< spawn_data< Handler, Function > > data_; -}; - -inline void default_spawn_handler() {} - -} - -template< typename Handler, typename Function > -void spawn( boost::asio::io_service& io_service, - BOOST_ASIO_MOVE_ARG( Handler) handler, - BOOST_ASIO_MOVE_ARG( Function) function) { - detail::spawn_helper< Handler, Function > helper; - helper.data_.reset( - new detail::spawn_data< Handler, Function >( - io_service, - BOOST_ASIO_MOVE_CAST( Handler)( handler), true, - BOOST_ASIO_MOVE_CAST( Function)( function) ) ); - boost_asio_handler_invoke_helpers::invoke( - helper, helper.data_->handler_); -} - -template< typename Handler, typename Function > -void spawn( basic_yield_context< Handler > ctx, - BOOST_ASIO_MOVE_ARG( Function) function) { - Handler handler( ctx.handler_); // Explicit copy that might be moved from. - detail::spawn_helper< Handler, Function > helper; - helper.data_.reset( - new detail::spawn_data< Handler, Function >( - BOOST_ASIO_MOVE_CAST( Handler)( handler), false, - BOOST_ASIO_MOVE_CAST( Function)( function) ) ); - boost_asio_handler_invoke_helpers::invoke( - helper, helper.data_->handler_); -} - -template< typename Function > -void spawn( boost::asio::io_service::strand strand, - BOOST_ASIO_MOVE_ARG( Function) function) { - boost::fibers::asio::spawn( - strand.get_io_service(), - strand.wrap( & detail::default_spawn_handler), - BOOST_ASIO_MOVE_CAST( Function)( function)); -} - -template< typename Function > -void spawn( boost::asio::io_service & io_service, - BOOST_ASIO_MOVE_ARG( Function) function) { - boost::fibers::asio::spawn( - boost::asio::io_service::strand( io_service), - BOOST_ASIO_MOVE_CAST( Function)( function)); -} - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_ASIO_DETAIL_SPAWN_HPP diff --git a/examples/asio/echo_server.cpp b/examples/asio/echo_server.cpp new file mode 100644 index 00000000..7eadb138 --- /dev/null +++ b/examples/asio/echo_server.cpp @@ -0,0 +1,123 @@ +// +// echo_server.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// 2013 Oliver Kowalke +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "round_robin.hpp" +#include "yield.hpp" + +using boost::asio::ip::tcp; + +const int max_length = 1024; + +typedef boost::shared_ptr< tcp::socket > socket_ptr; + +void session( socket_ptr sock) { + boost::fibers::fiber::id id = boost::this_fiber::get_id(); + std::cout << "fiber " << id << " : echo-handler started" << std::endl; + for (;;) { + char data[max_length]; + boost::system::error_code ec; + std::size_t length = sock->async_read_some( + boost::asio::buffer( data), + boost::fibers::asio::yield[ec]); + if ( ec == boost::asio::error::eof) { + break; //connection closed cleanly by peer + } else if ( ec) { + std::cerr << "fiber " << id << " : error occured : " << ec.message() << std::endl; + return; + } + boost::asio::async_write( + * sock, + boost::asio::buffer( data, length), + boost::fibers::asio::yield[ec]); + if ( ec == boost::asio::error::eof) { + break; //connection closed cleanly by peer + } else if ( ec) { + throw boost::system::system_error( ec); //some other error + } + } +} + +void server( boost::asio::io_service & io_service, unsigned short port) { + boost::fibers::fiber::id id = boost::this_fiber::get_id(); + std::cout << "fiber " << id << " : echo-server started" << std::endl; + tcp::acceptor a( io_service, tcp::endpoint( tcp::v4(), port) ); + for (;;) { + socket_ptr socket( new tcp::socket( io_service) ); + boost::system::error_code ec; + std::cout << "fiber " << id << " : accept new connection" << std::endl; + a.async_accept( + * socket, + boost::fibers::asio::yield[ec]); + if ( ec) { + std::cerr << "fiber " << id << " : error occured : " << ec.message() << std::endl; + } else { + boost::fibers::fiber( session, socket).detach(); + } + } +} + +int main( int argc, char* argv[]) { + try { + if ( 2 != argc) { + std::cerr << "Usage: echo_server \n"; + return EXIT_FAILURE; + } + boost::asio::io_service io_service; + boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_service); + // server fiber + boost::fibers::fiber( + server, boost::ref( io_service), std::atoi( argv[1]) ).detach(); + // fiber unrelated to asio + boost::fibers::fiber( + [](){ + boost::fibers::fiber::id id = boost::this_fiber::get_id(); + std::cout << "fiber " << id << " : sleeper tarted" << std::endl; + for ( int i = 0; i < 1; ++i) { + std::cout << "fiber " << id << " : sleeps for 1 second" << std::endl; + boost::this_fiber::sleep_for( std::chrono::seconds( 1) ); + } + std::cout << "fiber " << id << " : sleeps for 10 seconds" << std::endl; + boost::this_fiber::sleep_for( std::chrono::seconds( 2) ); + for ( int i = 0; i < 1; ++i) { + std::cout << "fiber " << id << " : sleeps for 1 second" << std::endl; + boost::this_fiber::sleep_for( std::chrono::seconds( 1) ); + } + } + ).detach(); + // fiber does shutdown the io_service + boost::fibers::fiber f([&io_service]() mutable { + boost::fibers::fiber::id id = boost::this_fiber::get_id(); + std::cout << "fiber " << id << " : shutdown io_service in 10 seconds" << std::endl; + boost::this_fiber::sleep_for( std::chrono::seconds( 10) ); + std::cout << "fiber " << id << " : shutdown" << std::endl; + io_service.stop(); + }); + // run io_service + io_service.run(); + // join fiber shutdown the io_service + f.join(); + return EXIT_SUCCESS; + } catch ( std::exception const& e) { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return EXIT_FAILURE; +} diff --git a/examples/asio/echo_server_spawn.cpp b/examples/asio/echo_server_spawn.cpp deleted file mode 100644 index d44fdae5..00000000 --- a/examples/asio/echo_server_spawn.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// 2013 Oliver Kowalke -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include - -#include -#include -#include - -#include -#include "round_robin.hpp" -#include "spawn.hpp" -#include "yield.hpp" - -using boost::asio::ip::tcp; - -const int max_length = 1024; - -typedef boost::shared_ptr< tcp::socket > socket_ptr; - -void session( socket_ptr sock) { - try { - std::cout << "handler request" << std::endl; - for (;;) { - char data[max_length]; - boost::system::error_code ec; - std::size_t length = sock->async_read_some( - boost::asio::buffer( data), - boost::fibers::asio::yield[ec]); - if ( ec == boost::asio::error::eof) { - break; //connection closed cleanly by peer - } else if ( ec) { - throw boost::system::system_error( ec); //some other error - } - boost::asio::async_write( - * sock, - boost::asio::buffer( data, length), - boost::fibers::asio::yield[ec]); - if ( ec == boost::asio::error::eof) { - break; //connection closed cleanly by peer - } else if ( ec) { - throw boost::system::system_error( ec); //some other error - } - } - } catch ( std::exception const& e) { - std::cerr << "Exception in fiber: " << e.what() << "\n"; - } -} - -void server( boost::asio::io_service & io_service, unsigned short port) { - tcp::acceptor a( io_service, tcp::endpoint( tcp::v4(), port) ); - for (;;) { - socket_ptr socket( new tcp::socket( io_service) ); - boost::system::error_code ec; - std::cout << "wait for accept" << std::endl; - a.async_accept( - * socket, - boost::fibers::asio::yield[ec]); - std::cout << "accepted" << std::endl; - if ( ! ec) { - boost::fibers::asio::spawn( - io_service, - boost::bind( session, socket) ); - } - } -} - -void foo( std::string const& msg) { - std::cout << "foo(): " << msg << std::endl; -} - -int main( int argc, char* argv[]) { - try { - if ( 2 != argc) { - std::cerr << "Usage: echo_server \n"; - return EXIT_FAILURE; - } - boost::asio::io_service io_service; - boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_service); - boost::fibers::asio::spawn( - io_service, - boost::bind( server, boost::ref( io_service), std::atoi( argv[1]) ) ); - boost::fibers::fiber( foo, "abc").detach(); - boost::fibers::fiber( - [](){ - for ( int i = 0; i < 20; ++i) { - std::cout << "loop " << i << std::endl; - boost::this_fiber::sleep_for( std::chrono::seconds( 1) ); - } - } - ).detach(); - boost::fibers::asio::run( io_service); - return EXIT_SUCCESS; - } catch ( std::exception const& e) { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return EXIT_FAILURE; -} diff --git a/examples/asio/echo_server_yield.cpp b/examples/asio/echo_server_yield.cpp deleted file mode 100644 index 91a93c2b..00000000 --- a/examples/asio/echo_server_yield.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// echo_server.cpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// 2013 Oliver Kowalke -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include - -#include -#include -#include - -#include -#include "round_robin.hpp" -#include "yield.hpp" - -using boost::asio::ip::tcp; - -const int max_length = 1024; - -typedef boost::shared_ptr< tcp::socket > socket_ptr; - -void session( socket_ptr sock) { - try { - std::cout << "handler request" << std::endl; - for (;;) { - char data[max_length]; - boost::system::error_code ec; - std::size_t length = sock->async_read_some( - boost::asio::buffer( data), - boost::fibers::asio::yield[ec]); - if ( ec == boost::asio::error::eof) { - break; //connection closed cleanly by peer - } else if ( ec) { - throw boost::system::system_error( ec); //some other error - } - boost::asio::async_write( - * sock, - boost::asio::buffer( data, length), - boost::fibers::asio::yield[ec]); - if ( ec == boost::asio::error::eof) { - break; //connection closed cleanly by peer - } else if ( ec) { - throw boost::system::system_error( ec); //some other error - } - } - } catch ( std::exception const& e) { - std::cerr << "Exception in fiber: " << e.what() << "\n"; - } -} - -void server( boost::asio::io_service & io_service, unsigned short port) { - tcp::acceptor a( io_service, tcp::endpoint( tcp::v4(), port) ); - for (;;) { - socket_ptr socket( new tcp::socket( io_service) ); - boost::system::error_code ec; - std::cout << "wait for accept" << std::endl; - a.async_accept( - * socket, - boost::fibers::asio::yield[ec]); - std::cout << "accepted" << std::endl; - if ( ! ec) { - boost::fibers::fiber( session, socket).detach(); - } - } -} - -int main( int argc, char* argv[]) { - try { - if ( 2 != argc) { - std::cerr << "Usage: echo_server \n"; - return EXIT_FAILURE; - } - boost::asio::io_service io_service; - boost::fibers::use_scheduling_algorithm< boost::fibers::asio::round_robin >( io_service); - boost::fibers::fiber( - server, boost::ref( io_service), std::atoi( argv[1]) ).detach(); - boost::fibers::asio::run( io_service); - return EXIT_SUCCESS; - } catch ( std::exception const& e) { - std::cerr << "Exception: " << e.what() << "\n"; - } - - return EXIT_FAILURE; -} diff --git a/examples/asio/ps/server.cpp b/examples/asio/ps/server.cpp index fa270b8e..441d8b82 100644 --- a/examples/asio/ps/server.cpp +++ b/examples/asio/ps/server.cpp @@ -27,7 +27,6 @@ #include #include "../round_robin.hpp" -#include "../spawn.hpp" #include "../yield.hpp" using boost::asio::ip::tcp; @@ -384,7 +383,7 @@ int main( int argc, char* argv[]) { boost::fibers::fiber( accept_subscriber, boost::ref( io_service), 9998, boost::ref( reg) ).detach(); // dispatch - boost::fibers::asio::run( io_service); + io_service.run(); return EXIT_SUCCESS; } catch ( std::exception const& e) { std::cerr << "Exception: " << e.what() << "\n"; diff --git a/examples/asio/round_robin.hpp b/examples/asio/round_robin.hpp index a1747dd1..0f096273 100644 --- a/examples/asio/round_robin.hpp +++ b/examples/asio/round_robin.hpp @@ -30,8 +30,7 @@ namespace boost { namespace fibers { namespace asio { -class round_robin : public boost::fibers::sched_algorithm, - public boost::asio::io_service::service { +class round_robin : public boost::fibers::sched_algorithm { private: std::size_t counter_{ 0 }; boost::asio::io_service & io_svc_; @@ -41,13 +40,27 @@ private: boost::fibers::condition_variable cnd_{}; public: - static boost::asio::io_service::id id; - round_robin( boost::asio::io_service & io_svc) : - boost::asio::io_service::service( io_svc), io_svc_( io_svc), suspend_timer_( io_svc_) { - boost::asio::add_service( io_svc, this); + io_svc_.post([this]() mutable { + while ( ! io_svc_.stopped() ) { + if ( has_ready_fibers() ) { + // run all pending handlers in round_robin + while ( io_svc_.poll() ); + // block this fiber till all pending (ready) fibers are processed + // == round_robin::suspend_until() has been called + std::unique_lock< boost::fibers::mutex > lk( mtx_); + cnd_.wait( lk); + } else { + // run one handler inside io_service + // if no handler available, block this thread + if ( ! io_svc_.run_one() ) { + break; + } + } + } + }); } void awakened( boost::fibers::context * ctx) noexcept { @@ -90,35 +103,8 @@ public: void notify() noexcept { suspend_timer_.expires_at( std::chrono::steady_clock::now() ); } - - void poll() { - io_svc_.dispatch([this]() mutable { - // boost::this_fiber::yield(); - std::unique_lock< boost::fibers::mutex > lk( mtx_); - cnd_.wait( lk); - }); - } - - void shutdown_service() { - } }; -boost::asio::io_service::id round_robin::id; - -void run( boost::asio::io_service & io_svc) { - BOOST_ASSERT( boost::asio::has_service< round_robin >( io_svc) ); - while ( ! io_svc.stopped() ) { - if ( boost::asio::use_service< round_robin >( io_svc).has_ready_fibers() ) { - while ( io_svc.poll() ); - boost::asio::use_service< round_robin >( io_svc).poll(); - } else { - if ( ! io_svc.run_one() ) { - break; - } - } - } -} - }}} #ifdef BOOST_HAS_ABI_HEADERS diff --git a/examples/asio/spawn.hpp b/examples/asio/spawn.hpp deleted file mode 100644 index a4bc409b..00000000 --- a/examples/asio/spawn.hpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// spawn.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_FIBERS_ASIO_SPAWN_HPP -#define BOOST_FIBERS_ASIO_SPAWN_HPP - -#include -#include -#include -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace asio { - -template< typename Handler > -class basic_yield_context { -public: - basic_yield_context( - boost::fibers::context * ctx, - Handler& handler) : - ctx_( ctx), - handler_( handler), - ec_( 0) { - } - - basic_yield_context operator[]( boost::system::error_code & ec) { - basic_yield_context tmp( * this); - tmp.ec_ = & ec; - return tmp; - } - -private: - boost::fibers::context * ctx_; - Handler & handler_; - boost::system::error_code * ec_; -}; - -typedef basic_yield_context< - boost::asio::detail::wrapped_handler< - boost::asio::io_service::strand, void(*)(), - boost::asio::detail::is_continuation_if_running> > yield_context; - -template< typename Handler, typename Function > -void spawn( boost::asio::io_service & io_service, - BOOST_ASIO_MOVE_ARG( Handler) handler, - BOOST_ASIO_MOVE_ARG( Function) function); - -template< typename Handler, typename Function > -void spawn( boost::asio::io_service & io_service, - basic_yield_context< Handler > ctx, - BOOST_ASIO_MOVE_ARG( Function) function); - -template< typename Function > -void spawn( boost::asio::io_service::strand strand, - BOOST_ASIO_MOVE_ARG( Function) function); - -template< typename Function > -void spawn( boost::asio::io_service & io_service, - BOOST_ASIO_MOVE_ARG( Function) function); - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#include "detail/spawn.hpp" - -#endif // BOOST_FIBERS_ASIO_SPAWN_HPP