tutorial.qbk

来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 2,067 行 · 第 1/5 页

QBK
2,067
字号
  ``''''''``  }  ``''''''``}  ``''''''``int main()  ``''''''``{  ``''''''``  boost::asio::io_service io;  ``''''''``  int count = 0;  ``''''''``  boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));  ``''''''``  t.async_wait(boost::bind(print,  ``''''''``        boost::asio::placeholders::error, &t, &count));  ``''''''``  io.run();  ``''''''``  std::cout << "Final count is " << count << "\n";  ``''''''``  return 0;  ``''''''``}Return to [link boost_asio.tutorial.tuttimer3 Timer.3 - Binding arguments to a handler][endsect][endsect][section:tuttimer4 Timer.4 - Using a member function as a handler]In this tutorial we will see how to use a class member function as a callback handler. The program should execute identically to the tutorial program from tutorial Timer.3.  ``''''''``#include <iostream>  ``''''''``#include <boost/asio.hpp>  ``''''''``#include <boost/bind.hpp>  ``''''''``#include <boost/date_time/posix_time/posix_time.hpp>Instead of defining a free function `print` as the callback handler, as we did in the earlier tutorial programs, we now define a class called `printer`.  ``''''''``class printer  ``''''''``{  ``''''''``public:The constructor of this class will take a reference to the io\_service object and use it when initialising the `timer_` member. The counter used to shut down the program is now also a member of the class.  ``''''''``  printer(boost::asio::io_service& io)  ``''''''``    : timer_(io, boost::posix_time::seconds(1)),  ``''''''``      count_(0)  ``''''''``  {The boost::bind() function works just as well with class member functions as with free functions. Since all non-static class member functions have an implicit `this` parameter, we need to bind `this` to the function. As in tutorial Timer.3, boost::bind() converts our callback handler (now a member function) into a function object that can be invoked as though it has the signature `void(const boost::system::error_code&)`.You will note that the boost::asio::placeholders::error placeholder is not specified here, as the `print` member function does not accept an error object as a parameter.  ``''''''``    timer_.async_wait(boost::bind(&printer::print, this));  ``''''''``  }In the class destructor we will print out the final value of the counter.  ``''''''``  ~printer()  ``''''''``  {  ``''''''``    std::cout << "Final count is " << count_ << "\n";  ``''''''``  }The `print` member function is very similar to the `print` function from tutorial Timer.3, except that it now operates on the class data members instead of having the timer and counter passed in as parameters.  ``''''''``  void print()  ``''''''``  {  ``''''''``    if (count_ < 5)  ``''''''``    {  ``''''''``      std::cout << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer_.async_wait(boost::bind(&printer::print, this));  ``''''''``    }  ``''''''``  }  ``''''''``private:  ``''''''``  boost::asio::deadline_timer timer_;  ``''''''``  int count_;  ``''''''``};The `main` function is much simpler than before, as it now declares a local `printer` object before running the io\_service as normal.  ``''''''``int main()  ``''''''``{  ``''''''``  boost::asio::io_service io;  ``''''''``  printer p(io);  ``''''''``  io.run();  ``''''''``  return 0;  ``''''''``}See the [link boost_asio.tutorial.tuttimer4.src full source listing]Return to the [link boost_asio.tutorial tutorial index]Previous: [link boost_asio.tutorial.tuttimer3 Timer.3 - Binding arguments to a handler]Next: [link boost_asio.tutorial.tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs][section:src Source listing for Timer.4]  ``''''''``//  ``''''''``// timer.cpp  ``''''''``// ~~~~~~~~~  ``''''''``//  ``''''''``// Copyright (c) 2003-2008 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)  ``''''''``//  ``''''''``#include <iostream>  ``''''''``#include <boost/asio.hpp>  ``''''''``#include <boost/bind.hpp>  ``''''''``#include <boost/date_time/posix_time/posix_time.hpp>  ``''''''``class printer  ``''''''``{  ``''''''``public:  ``''''''``  printer(boost::asio::io_service& io)  ``''''''``    : timer_(io, boost::posix_time::seconds(1)),  ``''''''``      count_(0)  ``''''''``  {  ``''''''``    timer_.async_wait(boost::bind(&printer::print, this));  ``''''''``  }  ``''''''``  ~printer()  ``''''''``  {  ``''''''``    std::cout << "Final count is " << count_ << "\n";  ``''''''``  }  ``''''''``  void print()  ``''''''``  {  ``''''''``    if (count_ < 5)  ``''''''``    {  ``''''''``      std::cout << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer_.async_wait(boost::bind(&printer::print, this));  ``''''''``    }  ``''''''``  }  ``''''''``private:  ``''''''``  boost::asio::deadline_timer timer_;  ``''''''``  int count_;  ``''''''``};  ``''''''``int main()  ``''''''``{  ``''''''``  boost::asio::io_service io;  ``''''''``  printer p(io);  ``''''''``  io.run();  ``''''''``  return 0;  ``''''''``}Return to [link boost_asio.tutorial.tuttimer4 Timer.4 - Using a member function as a handler][endsect][endsect][section:tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs]This tutorial demonstrates the use of the boost::asio::strand class to synchronise callback handlers in a multithreaded program.The previous four tutorials avoided the issue of handler synchronisation by calling the [link boost_asio.reference.io_service.run io_service::run()] function from one thread only. As you already know, the asio library provides a guarantee that callback handlers will only be called from threads that are currently calling [link boost_asio.reference.io_service.run io_service::run()]. Consequently, calling [link boost_asio.reference.io_service.run io_service::run()] from only one thread ensures that callback handlers cannot run concurrently.The single threaded approach is usually the best place to start when developing applications using asio. The downside is the limitations it places on programs, particularly servers, including:* Poor responsiveness when handlers can take a long time to complete. * An inability to scale on multiprocessor systems. If you find yourself running into these limitations, an alternative approach is to have a pool of threads calling [link boost_asio.reference.io_service.run io_service::run()]. However, as this allows handlers to execute concurrently, we need a method of synchronisation when handlers might be accessing a shared, thread-unsafe resource.  ``''''''``#include <iostream>  ``''''''``#include <boost/asio.hpp>  ``''''''``#include <boost/thread.hpp>  ``''''''``#include <boost/bind.hpp>  ``''''''``#include <boost/date_time/posix_time/posix_time.hpp>We start by defining a class called `printer`, similar to the class in the previous tutorial. This class will extend the previous tutorial by running two timers in parallel.  ``''''''``class printer  ``''''''``{  ``''''''``public:In addition to initialising a pair of boost::asio::deadline\_timer members, the constructor initialises the `strand_` member, an object of type boost::asio::strand.An boost::asio::strand guarantees that, for those handlers that are dispatched through it, an executing handler will be allowed to complete before the next one is started. This is guaranteed irrespective of the number of threads that are calling [link boost_asio.reference.io_service.run io_service::run()]. Of course, the handlers may still execute concurrently with other handlers that were not dispatched through an boost::asio::strand, or were dispatched through a different boost::asio::strand object.  ``''''''``  printer(boost::asio::io_service& io)  ``''''''``    : strand_(io),  ``''''''``      timer1_(io, boost::posix_time::seconds(1)),  ``''''''``      timer2_(io, boost::posix_time::seconds(1)),  ``''''''``      count_(0)  ``''''''``  {When initiating the asynchronous operations, each callback handler is "wrapped" using the boost::asio::strand object. The [link boost_asio.reference.io_service__strand.wrap strand::wrap()] function returns a new handler that automatically dispatches its contained handler through the boost::asio::strand object. By wrapping the handlers using the same boost::asio::strand, we are ensuring that they cannot execute concurrently.  ``''''''``    timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));  ``''''''``    timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));  ``''''''``  }  ``''''''``  ~printer()  ``''''''``  {  ``''''''``    std::cout << "Final count is " << count_ << "\n";  ``''''''``  }In a multithreaded program, the handlers for asynchronous operations should be synchronised if they access shared resources. In this tutorial, the shared resources used by the handlers (`print1` and `print2`) are `std::cout` and the `count_` data member.  ``''''''``  void print1()  ``''''''``  {  ``''''''``    if (count_ < 10)  ``''''''``    {  ``''''''``      std::cout << "Timer 1: " << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));  ``''''''``    }  ``''''''``  }  ``''''''``  void print2()  ``''''''``  {  ``''''''``    if (count_ < 10)  ``''''''``    {  ``''''''``      std::cout << "Timer 2: " << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));  ``''''''``    }  ``''''''``  }  ``''''''``private:  ``''''''``  boost::asio::strand strand_;  ``''''''``  boost::asio::deadline_timer timer1_;  ``''''''``  boost::asio::deadline_timer timer2_;  ``''''''``  int count_;  ``''''''``};The `main` function now causes [link boost_asio.reference.io_service.run io_service::run()] to be called from two threads: the main thread and one additional thread. This is accomplished using an boost::thread object.Just as it would with a call from a single thread, concurrent calls to [link boost_asio.reference.io_service.run io_service::run()] will continue to execute while there is "work" left to do. The background thread will not exit until all asynchronous operations have completed.  ``''''''``int main()  ``''''''``{  ``''''''``  boost::asio::io_service io;  ``''''''``  printer p(io);  ``''''''``  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));  ``''''''``  io.run();  ``''''''``  t.join();  ``''''''``  return 0;  ``''''''``}See the [link boost_asio.tutorial.tuttimer5.src full source listing]Return to the [link boost_asio.tutorial tutorial index]Previous: [link boost_asio.tutorial.tuttimer4 Timer.4 - Using a member function as a handler][section:src Source listing for Timer.5]  ``''''''``//  ``''''''``// timer.cpp  ``''''''``// ~~~~~~~~~  ``''''''``//  ``''''''``// Copyright (c) 2003-2008 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)  ``''''''``//  ``''''''``#include <iostream>  ``''''''``#include <boost/asio.hpp>  ``''''''``#include <boost/thread.hpp>  ``''''''``#include <boost/bind.hpp>  ``''''''``#include <boost/date_time/posix_time/posix_time.hpp>  ``''''''``class printer  ``''''''``{  ``''''''``public:  ``''''''``  printer(boost::asio::io_service& io)  ``''''''``    : strand_(io),  ``''''''``      timer1_(io, boost::posix_time::seconds(1)),  ``''''''``      timer2_(io, boost::posix_time::seconds(1)),  ``''''''``      count_(0)  ``''''''``  {  ``''''''``    timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));  ``''''''``    timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));  ``''''''``  }  ``''''''``  ~printer()  ``''''''``  {  ``''''''``    std::cout << "Final count is " << count_ << "\n";  ``''''''``  }  ``''''''``  void print1()  ``''''''``  {  ``''''''``    if (count_ < 10)  ``''''''``    {  ``''''''``      std::cout << "Timer 1: " << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));  ``''''''``    }  ``''''''``  }  ``''''''``  void print2()  ``''''''``  {  ``''''''``    if (count_ < 10)  ``''''''``    {  ``''''''``      std::cout << "Timer 2: " << count_ << "\n";  ``''''''``      ++count_;  ``''''''``      timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));  ``''''''``      timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));  ``''''''``    }  ``''''''``  }  ``''''''``private:  ``''''''``  boost::asio::strand strand_;  ``''''''``  boost::asio::deadline_timer timer1_;  ``''''''``  boost::asio::deadline_timer timer2_;  ``''''''``  int count_;  ``''''''``};  ``''''''``int main()  ``''''''``{  ``''''''``  boost::asio::io_service io;  ``''''''``  printer p(io);  ``''''''``  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));  ``''''''``  io.run();  ``''''''``  t.join();  ``''''''``  return 0;  ``''''''``}Return to [link boost_asio.tutorial.tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs][endsect]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?