代码之家  ›  专栏  ›  技术社区  ›  LogicStuff

boost.asio-不执行所有处理程序

  •  0
  • LogicStuff  · 技术社区  · 7 年前

    我正在尝试为 boost::io_context ,这将始终在准备好执行的处理程序中选择优先级最高的处理程序。我的灵感来自 the official example 但在一个场景中很快遇到意外行为,其中一个处理程序在同一上下文中启动另一个异步操作。

    这里是 MCVE . 我只修改了用户代码(如下 //--- )调用一个低优先级处理程序,在此之后,我希望调用高优先级和中优先级处理程序。只调用低优先级处理程序。

    #include <boost/asio.hpp>
    #include <boost/function.hpp>
    #include <iostream>
    #include <queue>
    
    class handler_priority_queue
    {
    public:
      void add(int priority, boost::function<void()> function)
      {
        handlers_.push(queued_handler(priority, function));
      }
    
      void execute_all()
      {
        while (!handlers_.empty())
        {
          queued_handler handler = handlers_.top();
          handler.execute();
          handlers_.pop();
        }
      }
    
      // A generic wrapper class for handlers to allow the invocation to be hooked.
      template <typename Handler>
      class wrapped_handler
      {
      public:
        wrapped_handler(handler_priority_queue& q, int p, Handler h)
          : queue_(q), priority_(p), handler_(h)
        {
        }
    
        void operator()()
        {
          handler_();
        }
    
        template <typename Arg1>
        void operator()(Arg1 arg1)
        {
          handler_(arg1);
        }
    
        template <typename Arg1, typename Arg2>
        void operator()(Arg1 arg1, Arg2 arg2)
        {
          handler_(arg1, arg2);
        }
    
      //private:
        handler_priority_queue& queue_;
        int priority_;
        Handler handler_;
      };
    
      template <typename Handler>
      wrapped_handler<Handler> wrap(int priority, Handler handler)
      {
        return wrapped_handler<Handler>(*this, priority, handler);
      }
    
    private:
      class queued_handler
      {
      public:
        queued_handler(int p, boost::function<void()> f)
          : priority_(p), function_(f)
        {
        }
    
        void execute()
        {
          function_();
        }
    
        friend bool operator<(const queued_handler& a,
            const queued_handler& b)
        {
          return a.priority_ < b.priority_;
        }
    
      private:
        int priority_;
        boost::function<void()> function_;
      };
    
      std::priority_queue<queued_handler> handlers_;
    };
    
    // Custom invocation hook for wrapped handlers.
    template <typename Function, typename Handler>
    void asio_handler_invoke(Function f,
        handler_priority_queue::wrapped_handler<Handler>* h)
    {
      h->queue_.add(h->priority_, f);
    }
    
    //----------------------------------------------------------------------
    
    void high_priority_handler()
    {
      std::cout << "High priority handler\n";
    }
    
    void middle_priority_handler()
    {
      std::cout << "Middle priority handler\n";
    }
    
    void low_priority_handler(
      boost::asio::io_service& io_service,
      handler_priority_queue& pri_queue)
    {
      std::cout << "Low priority handler\n";
    
      io_service.post(pri_queue.wrap(1, middle_priority_handler));
      io_service.post(pri_queue.wrap(2, high_priority_handler));
    }
    
    int main()
    {
      boost::asio::io_service io_service;
      handler_priority_queue pri_queue;
    
      // Post a completion handler to be run immediately.
      io_service.post(pri_queue.wrap(
          0, std::bind(low_priority_handler,
                       std::ref(io_service), std::ref(pri_queue))));
    
      while (io_service.run_one())
      {
        // The custom invocation hook adds the handlers to the priority queue
        // rather than executing them from within the poll_one() call.
        while (io_service.poll_one())
          ;
    
        pri_queue.execute_all();
      }
    
      return 0;
    }
    

    如果我打电话 io_service.restart() 循环后 main 然后复制粘贴相同的循环,然后按预期的顺序执行其余的处理程序。调试时,我可以看到一个处理程序已排队进入 asio_handler_invoke 只有一次。

    为什么 boost::IO环境 停止在第一个处理程序之后运行?我要求的是可能的吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   rafix07    7 年前

    io_context 停止,因为没有任何就绪的处理程序可在 poll_one 被称为。

    [1]发布第一个处理程序:

    io_service.post(pri_queue.wrap(0, std::bind(low_priority_handler,
                       std::ref(io_service), std::ref(pri_queue))));
    

    〔2〕 while (io_service.run_one())

    等待直到有一个就绪的处理程序可以运行

    〔3〕 run_one() 已执行处理程序。你已经定义了 asio_handler_invoke() 它提供了一些策略来调用处理程序的函数(主体)。默认策略只是调用函数,在这种情况下,函数对象排队进入 handler_priority_queue 但是 io_service's 队列不接收要执行的处理程序。所以,当身体 low_priority_handler (这将为添加新的处理程序) io_service 通过呼叫 io_service.post )执行吗?此函数的执行位置 pri_queue.execute_all() ( 在后面叫 波利酮 ,不是在呼叫期间 poll_one() . io_service.poll_one() 标志 信息服务 当没有任何准备好运行的处理程序时停止。这是你的案子。你可以重置 信息服务 之后 pri_queue.execute_all() ,则将调用所有处理程序。

    推荐文章