1[/ 2 Copyright Oliver Kowalke 2013. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt 6] 7 8[section:asio Example: asynchronous network I/O (boost.asio)] 9 10In the past, code using asio's ['asynchronous operations] was scattered by 11callbacks. 12__boost_asio__ provides with its new ['asynchronous result] feature a new way to 13simplify the code and make it easier to read. 14__yield_context__ internally uses __boost_coroutine__: 15 16 void echo(boost::asio::ip::tcp::socket& socket,boost::asio::yield_context yield){ 17 char data[128]; 18 // read asynchronous data from socket 19 // execution context will be suspended until 20 // some bytes are read from socket 21 std::size_t n=socket.async_read_some(boost::asio::buffer(data),yield); 22 // write some bytes asynchronously 23 boost::asio::async_write(socket,boost::asio::buffer(data,n),yield); 24 } 25 26Unfortunately __boost_coroutine__ (__yield_context__) does not provide 27primitives to synchronize different coroutines (execution contexts). 28 29__boost_fiber__ provides an example how __fibers__ could be integrated into 30__boost_asio__ so that ['asynchronous operations] from __boost_asio__ can be 31used together with fibers, synchronized by primitives provided by 32__boost_fiber__. 33 34The example section contains a complete publish-subscribe application 35demonstrating the use of fibers with asio's ['asynchronous operations]. 36__yield_fiber__ abstracts the fiber in asio's context. 37 38 void subscriber::run( boost::fibers::asio::yield_fiber yield) 39 { 40 boost::system::error_code ec; 41 42 // read first message == queue name 43 std::string queue; 44 boost::asio::async_read( 45 socket_, 46 boost::asio::buffer( queue), 47 yield[ec]); 48 if ( ec) throw std::runtime_error("no queue from subscriber"); 49 50 // register new queue 51 reg_.subscribe( queue, shared_from_this() ); 52 53 for (;;) 54 { 55 boost::fibers::mutex::scoped_lock lk( mtx_); 56 // wait for published messages 57 // fiber gets suspended and will be woken up if a 58 // new message has to be published to subscriber 59 cond_.wait( lk); 60 61 // '<fini>' terminates subscriber 62 // data_ is a private member of subscriber and 63 // gets filled by the publisher 64 // notification of available data via condition_var cond_ 65 if ( "<fini>" == std::string( data_) ) break; 66 67 // write message asynchronously to subscriber 68 // fiber gets suspended until message was written 69 boost::asio::async_write( 70 socket_, 71 boost::asio::buffer( data_, max_length), 72 yield[ec]); 73 if ( ec) throw std::runtime_error("publishing message failed"); 74 } 75 } 76 77[heading C10K problem] 78 79The C10K-website [footnote [@http://www.kegel.com/c10k.html 'The C10K problem', 80Dan Kegel]] 81from Dan Kegel describes the problem of handling ten thousand clients 82simultaneously and which strategies are possible. 83 84__boost_fiber__ and __boost_asio__ support the strategy 'serve many clients with 85each server thread, and use asynchronous I/O' without scattering the logic 86across many callbacks (as was asio's previous strategy) and overloading the 87operating system with too many threads. (Beyond a certain number of threads, the 88overhead of the kernel scheduler starts to swamp the available cores.) 89 90Because __boost_fiber__ contains synchronization primitives, it is easy to 91synchronize different fibers and use asynchronous network I/O at the same 92time. 93 94__boost_fiber__ provides the same classes and interfaces as __boost_thread__. 95Therefore developers are able to use patterns familiar from multi-threaded 96programming. For instance the strategy 'serve one client with one thread' 97could be transformed into 'serve one client with one fiber'. 98 99[heading Integration] 100 101The code for integrating boost.fiber int boost.asio can be found in the example 102directory. The author believes, that a better, more tight integration is 103possible but requires input of boost.asio's author and maybe some changes in the 104boost.asio framework. 105 106The current integration pattern requires to runn __io_service__ in 107__run_service__ (separate fiber). 108 109 110[endsect] 111