gpt4 book ai didi

c++ - 提升 asio 优先级队列,从处理程序添加异步操作

转载 作者:行者123 更新时间:2023-11-30 05:41:50 31 4
gpt4 key购买 nike

我对基于 boost asio 优先级队列示例的设计有疑问。如果我从处理程序中添加一个包装的处理程序,它似乎会丢失:

参见 http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp03/invocation/prioritised_handlers.cpp例如。

我按原样使用了所有内容,并将 main() 函数替换为以下代码:

//
// based on prioritised_handlers.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 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 <boost/asio.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <queue>

using boost::asio::ip::tcp;

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 low_priority_handler()
{
std::cout << "Low priority handler\n";
}

int main()
{
//
// BASED ON prioritised_handlers.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 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)
//



//----------------------------------------------------------------------
using boost::asio::ip::tcp;
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, low_priority_handler));


// Set a deadline timer to expire immediately.
boost::asio::deadline_timer timer1(io_service);
timer1.expires_at(boost::posix_time::neg_infin);
timer1.async_wait(pri_queue.wrap(42, [](const boost::system::error_code& )
{
std::cout << "now" << std::endl;
}));
// Set a deadline timer to expire later.
boost::asio::deadline_timer timer2(io_service, boost::posix_time::milliseconds(100));
boost::asio::deadline_timer timer3(io_service, boost::posix_time::milliseconds(200));
timer2.async_wait(pri_queue.wrap(100, [&pri_queue, &timer3](const boost::system::error_code& )
{
std::cout << "100ms" << std::endl;
timer3.async_wait(pri_queue.wrap(100, [](const boost::system::error_code& )
{
std::cout << "200ms" << std::endl;
}));

}));

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();
}
}

//g++ -std=c++14 -Wall -Werror -rdynamic -lboost_system -lboost_thread -lboost_log -lpthread prioritised_handlers.cpp

这打印:

now
Low priority handler
100ms

Timer3 的 200ms 打印输出丢失了。根据我的 printf 调试方法,自定义调用 Hook asio_handler_invoke() 永远不会为“200ms”操作调用。不幸的是,我不明白为什么。

上述方法有什么问题?

在 Technik 的提示后用示例的其余部分更新了代码

最佳答案

除了您保持(或更确切地说不保持)应用程序存活足够长的时间以使最后一个处理程序完成之外,任何代码都没有问题。

您正在运行 io_service,轮询并运行每个作业。所有作业都得到处理,但它们是延迟的异步调用。您指望 io_service 调用使应用程序保持事件状态,但就 io_service 而言,所有工作都已完成,因此它停止阻塞,您的 main() 函数退出并且您永远看不到最终处理程序的输出.

为了向您证明这一点,只需将 io_service 包装在 ::work 对象中,这将防止 io_service 认为这是它没有工作要做,因此总是阻塞。

boost::asio::io_service::work w(io_service);

将此添加到您的 while (io_service.run_one()) 行之前。

关于c++ - 提升 asio 优先级队列,从处理程序添加异步操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31020020/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com