C++ Asio-不执行所有处理程序

C++ Asio-不执行所有处理程序,c++,asynchronous,boost,boost-asio,C++,Asynchronous,Boost,Boost Asio,我正在尝试为boost::io_context创建一个适配器,它总是在准备好的处理程序中选择优先级最高的处理程序来执行。我从中得到了灵感,但很快在一个场景中遇到了意想不到的行为,在这个场景中,一个处理程序在相同的上下文中启动另一个异步操作 这是你的电话号码。我只修改了用户代码(在/-下面),以调用低优先级处理程序,之后我希望调用高优先级和中优先级处理程序。只调用低优先级处理程序 #include <boost/asio.hpp> #include <boost/function

我正在尝试为
boost::io_context
创建一个适配器,它总是在准备好的处理程序中选择优先级最高的处理程序来执行。我从中得到了灵感,但很快在一个场景中遇到了意想不到的行为,在这个场景中,一个处理程序在相同的上下文中启动另一个异步操作

这是你的电话号码。我只修改了用户代码(在
/-
下面),以调用低优先级处理程序,之后我希望调用高优先级和中优先级处理程序。只调用低优先级处理程序

#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;
}
#包括
#包括
#包括
#包括
类处理程序\u优先级\u队列
{
公众:
void add(int优先级,boost::function)
{
处理程序推送(队列处理程序(优先级、函数));
}
void execute_all()
{
而(!handlers.empty())
{
排队的_handler=handlers_u.top();
handler.execute();
处理程序.pop();
}
}
//用于处理程序的通用包装类,允许挂接调用。
模板
类包装的\u处理程序
{
公众:
包装处理程序(处理程序优先级队列&q、int p、处理程序h)
:队列(q)、优先级(p)、处理程序(h)
{
}
void运算符()()
{
handler_();
}
模板
void运算符()(Arg1 Arg1)
{
handler(arg1);
}
模板
void运算符()(Arg1 Arg1、Arg2 Arg2)
{
处理器(arg1,arg2);
}
//私人:
处理程序\u优先级\u队列和队列\u;
int优先权u2;;
处理程序;
};
模板
wrapped\u处理程序wrapp(int优先级,处理程序)
{
返回包装的处理程序(*此,优先级,处理程序);
}
私人:
类队列处理程序
{
公众:
排队_处理程序(int p,boost::function f)
:优先级(p),功能(f)
{
}
void execute()
{
函数_();
}
友元布尔运算符队列添加(h->priority,f);
}
//----------------------------------------------------------------------
无效高优先级处理程序()
{

std::cout
io\u context
停止,因为在调用
poll\u one
时没有任何准备好的处理程序可以运行

#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;
}
[1] 第一个处理程序已发布:

io_service.post(pri_queue.wrap(0, std::bind(low_priority_handler,
                   std::ref(io_service), std::ref(pri_queue))));
[2]
while(io_服务。运行_one())

等待直到有一个准备好的处理程序运行


[3] 在
run\u one()
handler中执行。您已经定义了
asio\u handler\u invoke()
,它提供了一些调用函数(主体)的策略默认策略只是调用函数,在您的情况下,函数对象被排队到
handler\u priority\u queue
,但
io\u服务的
队列不接收要执行的处理程序。因此,当
低优先级\u处理程序的主体
(通过调用
io\u service.post
)为
io\u服务添加新的处理程序)是否执行?此函数从
pri\u queue.execute\u all()
poll\u one
poll\u one()调用后调用),而不是在
poll\u one()调用期间执行
io\u服务
标记为在没有任何就绪处理程序可运行时停止。这是您的情况。您可以在
pri\u队列之后重置
io\u服务
。执行所有()
,则将调用所有处理程序。

io_上下文
停止,因为在调用poll_one
时,没有任何准备好的处理程序可运行

#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;
}
[1] 第一个处理程序已发布:

io_service.post(pri_queue.wrap(0, std::bind(low_priority_handler,
                   std::ref(io_service), std::ref(pri_queue))));
[2]
while(io_服务。运行_one())

等待直到有一个准备好的处理程序运行

[3] 在
run\u one()
handler中执行。您已经定义了
asio\u handler\u invoke()
,它提供了一些调用函数(主体)的策略默认策略只是调用函数,在您的情况下,函数对象被排队到
handler\u priority\u queue
,但
io\u服务的
队列不接收要执行的处理程序。因此,当
低优先级\u处理程序的主体
(通过调用
io\u service.post
)为
io\u服务添加新的处理程序)是否执行?此函数从
pri\u queue.execute\u all()
poll\u one
poll\u one()调用后调用),而不是在
poll\u one()调用期间执行
io\u服务
标记为在没有任何准备好的处理程序运行时停止。这是您的情况。您可以在
pri\u队列之后重置
io\u服务
。执行\u all()
,然后调用所有处理程序