C++11 使用Boost.Asio,如果没有IO事件,是否可以添加一个处理程序,该处理程序在事件循环的每个迭代中执行一次?
我目前正在使用Boost.asio1.68编写一个简单的服务器,我想知道是否有一种方法可以添加一个处理程序,在事件循环没有其他工作要做时执行 目前我有:C++11 使用Boost.Asio,如果没有IO事件,是否可以添加一个处理程序,该处理程序在事件循环的每个迭代中执行一次?,c++11,event-handling,boost-asio,C++11,Event Handling,Boost Asio,我目前正在使用Boost.asio1.68编写一个简单的服务器,我想知道是否有一种方法可以添加一个处理程序,在事件循环没有其他工作要做时执行 目前我有: void completionHandler (boost::asio::io_context* ioCtx){ // poll for some condition // if (condition) do some work; ioCtx->post(boost::bind(completionHandler, ioCtx
void completionHandler (boost::asio::io_context* ioCtx){
// poll for some condition
// if (condition) do some work;
ioCtx->post(boost::bind(completionHandler, ioCtx));
}
//elsewhere
ioCtx->post(boost::bind(completionHandler, ioCtx));
但是,这与我想要做的并不完全匹配。这不会达到您期望的效果 例如,使用单个
async\u accept
循环,您将永远不会达到“没有其他工作要做”的程度
同样,如果只有一方拥有未完成的工作
(和),则永远不会出现“没有其他工作要做”的情况
基本上,您真正想要做的是链接轮询:
template <typename Condition, typename Handler, typename Executor>
void run_when(Executor& ex, Condition c, Handler h) {
struct Op {
Executor& _executor;
Condition _cond;
Handler _handler;
Op(Executor& ex, Condition c, Handler h)
: _executor(ex), _cond(std::move(c)), _handler(std::move(h))
{ }
void operator()() const {
if (_cond())
_handler(error_code{});
else
ba::post(_executor, std::move(*this));
}
};
ba::post(ex, Op{ex, std::move(c), std::move(h)});
}
奖金
为什么我们的处理程序接受错误代码?嗯,与其他Asio操作一样,您可能希望能够取消它们。当(…)::Op实例时,要么让调用者负责延长运行单元的生命周期,这会使生命变得复杂。或者,您可以使条件
可调用项返回一个代码,指示该条件是否满足或等待是否已放弃\:
或
取决于随机延迟()
的值
1(或者市长的女儿离婚了,因为错误代码非常通用)警告:在现实生活中,你想限制你的回调链,因为如果没有其他东西排队,它将近似于一个繁忙的循环。
run_when(io,
[&] { return bool(triggered); },
[](error_code ec) { std::clog << "triggered: " << ec.message() << "\n"; });
#include <boost/asio.hpp>
namespace ba = boost::asio;
using boost::system::error_code;
using namespace std::chrono_literals;
template <typename Condition, typename Handler, typename Executor>
void run_when(Executor& ex, Condition c, Handler h) {
struct RunWhen {
Executor& _executor;
Condition _cond;
Handler _handler;
RunWhen(Executor& ex, Condition c, Handler h)
: _executor(ex), _cond(std::move(c)), _handler(std::move(h))
{ }
void operator()() const {
if (_cond())
_handler(error_code{});
else
ba::post(_executor, std::move(*this));
}
};
ba::post(ex, RunWhen{ex, std::move(c), std::move(h)});
}
#include <iostream>
int main() {
// some state that gets changed in the background
std::atomic_bool triggered { false };
std::thread([&] {
std::this_thread::sleep_for(1.5s);
triggered = true;
}).detach();
ba::io_context io;
// just some background polling that shall not block other work
run_when(io, [&] { return bool(triggered); }, [](error_code ec) { std::clog << "triggered: " << ec.message() << "\n"; });
io.run_for(3s);
}
triggered: Success
#include <boost/asio.hpp>
namespace ba = boost::asio;
using boost::system::error_code;
using boost::system::system_error;
using ba::error::operation_aborted;
using namespace std::chrono_literals;
template <typename Condition, typename Handler, typename Executor>
void run_when(Executor& ex, Condition c, Handler h) {
struct Op {
Executor& _executor;
Condition _cond;
Handler _handler;
Op(Executor& ex, Condition c, Handler h)
: _executor(ex), _cond(std::move(c)), _handler(std::move(h))
{ }
void operator()() const {
try {
if (_cond())
_handler(error_code{});
else
ba::post(_executor, std::move(*this));
} catch(system_error const& se) {
_handler(se.code());
}
}
};
ba::post(ex, Op{ex, std::move(c), std::move(h)});
}
#include <random>
auto random_delay() {
static std::mt19937 engine(std::random_device{}());
return (std::uniform_int_distribution<>(1,2)(engine)) * 1s;
}
#include <iostream>
int main() {
// some state that gets changed in the background
std::atomic_bool triggered { false }, canceled { false };
std::thread([&] { std::this_thread::sleep_for(1.5s); triggered = true; }).detach();
// add a randomized cancellation
{
auto cancel_time = random_delay();
std::clog << "hammer time: " << (cancel_time/1.0s) << "s\n";
std::thread([&] { std::this_thread::sleep_for(cancel_time); canceled = true; }).detach();
}
ba::io_context io;
// just some background polling that shall not block other work
auto condition = [&] { return canceled? throw system_error(operation_aborted) : bool(triggered); };
run_when(io, condition, [](error_code ec) { std::clog << "handler: " << ec.message() << "\n"; });
io.run_for(3s);
}
hammer time: 1s
handler: Success
hammer time: 2s
handler: Success