zoukankan      html  css  js  c++  java
  • Boost.ASIO简要分析-2 timer实例分析

    2. timer实例分析

    下面分别介绍下同步操作实例与异步操作实例

    2.1 同步操作实例

    下面简单解释下官方文档中的定时器同步等待例子

    #include <iostream>
    
    #include <boost/asio.hpp>
    
    #include <boost/date_time/posix_time/posix_time.hpp>
    
    int main()
    
    {
    
      boost::asio::io_service io; // 定义一个io_service对象
    
      boost::asio::deadline_timer t(io, boost::posix_time::seconds(5)); //定义一个deadline_timer对象,注意上面的io作为其参数。
    
      t.wait(); // 同步等待5秒。线程会在这边休息一小会~~
    
      std::cout << "Hello, world!
    ";
    
      return 0;
    
    }
    2.2 异步操作实例

    下面简单解释下官方文档中的定时器异步等待例子

    #include <iostream>
    
    #include <boost/asio.hpp>
    
    #include <boost/date_time/posix_time/posix_time.hpp>
    
    // 这是一个回调函数
    
    void print(const boost::system::error_code& /*e*/)
    
    {
    
      std::cout << "Hello, world!
    ";
    
    }
    
    int main()
    
    {
    
      boost::asio::io_service io;
    
      boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
    
      t.async_wait(&print); // 这里的函数是以async开头的,表示是异步函数
    
      io.run(); // 因为上面调用异步函数async_wait,所以函数很快完成,并来到这里。
    
      return 0;
    
    }
    2.3 io_service::run分析

    看到2.2的异步代码,不免会对io_service::run函数好奇。下面简要分析下。

    std::size_t io_service::run()
    
    {
    
      boost::system::error_code ec;
    
      std::size_t s = impl_.run(ec); // 主要实现代码在这句中
    
      boost::asio::detail::throw_error(ec);
    
      return s;
    
    }

    不同的平台,实现代码不一样。下面以windows环境为例。

    size_t win_iocp_io_service::run(boost::system::error_code& ec)
    
    {
    
    // 判断是否有异步事件,没有的话就直接返回。
    
    // 如果客户端调用异步函数(比如2.2中的t.wait()),则会调用函数 ::InterlockedIncrement(&outstanding_work_)将任务数加1。
    
      if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
    
      {
    
        stop();
    
        ec = boost::system::error_code();
    
        return 0;
    
      }
    
      win_iocp_thread_info this_thread;
    
      thread_call_stack::context ctx(this, this_thread);
    
      size_t n = 0;
    
      while (do_one(true, ec)) // 循环调用,直到返回false
    
        if (n != (std::numeric_limits<size_t>::max)())
    
          ++n;
    
      return n;
    
    }

    Windows下面实现异步操作是以I/O完成端口为基础的。下面简单分析下do_one这个核心函数。省略部分非关键代码。

    size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
    
    {
    
      for (;;)
    
      {
    
    ......
    
        // Get the next operation from the queue.
    
        DWORD bytes_transferred = 0;
    
        dword_ptr_t completion_key = 0;
    
        LPOVERLAPPED overlapped = 0;
    
        ::SetLastError(0);
    
        BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
    
            &completion_key, &overlapped, block ? gqcs_timeout_ : 0); // 尝试从I/O完成端口读取I/O完成包。
    
        DWORD last_error = ::GetLastError();
    
        if (overlapped)
    
        {
    
          win_iocp_operation* op = static_cast<win_iocp_operation*>(overlapped);
    
          boost::system::error_code result_ec(last_error,
    
              boost::asio::error::get_system_category());
    
        ......
    
          if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
    
          {
    
            // Ensure the count of outstanding work is decremented on block exit.
    
            work_finished_on_block_exit on_exit = { this };
    
            (void)on_exit;
    
            op->complete(*this, result_ec, bytes_transferred); // 此处是关键调用
    
            ec = boost::system::error_code();
    
            return 1;
    
          }
    
        }
    
    ......
    
      }
    
    }

    op->complete(*this, result_ec, bytes_transferred)函数的作用就是回调之前注册的函数(如2.2中的print函数)。看下调用堆栈就更清楚了,如下图。

    wps664D.tmp

  • 相关阅读:
    JS 操作属性
    JS 操作对象 事件 样式
    JS 一个页面关闭多个页面
    JS DOM
    JS 语言基础
    JS 基础知识
    CSS样式表
    HTML 常用标记
    HTML iframe框架
    28-2 logging 日志模块
  • 原文地址:https://www.cnblogs.com/SudoSky/p/4508555.html
Copyright © 2011-2022 走看看