asio.qbk 4.5 KB

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