boost::asio::deadline_timer 绑定到多态套接字类指针
Posted
技术标签:
【中文标题】boost::asio::deadline_timer 绑定到多态套接字类指针【英文标题】:boost::asio::deadline_timer binding to a polymorphic socket class pointer 【发布时间】:2016-05-01 22:57:23 【问题描述】:我的方案(或多或少)如下:
asio_socket
是带有单个纯虚方法的 abc:
virtual void schedule(
boost::asio::ip::tcp::resolver::query &,
boost::asio::ip::tcp::resolver &,
boost::asio::io_service &
) = 0;
另一个类asio_socket_http
继承自它,也继承自另一个asio_helper
。另一个类asio_socket_https
也遵循相同的方案。
asio_socket_http
实现了 asio_async 处理程序,用于 http 连接。
其他类(定义特定的 URI/URL 相关操作)继承自 asio_socket_http
或 asio_socket_https
。
存在一个作业调度器:
void run_job(const std::shared_ptr<asio_socket> job);
它在内部所做的只是:
void run_job(const std::shared_ptr<asio_socket> job)
boost::asio::io_service io;
boost::asio::ip::tcp::resolver resolver(io);
job->schedule(query_, resolver, io);
io.run();
我想添加一个截止时间计时器,它将处理 asio 的异步性质:
void run_job(const std::shared_ptr<asio_socket> job)
boost::asio::io_service io;
boost::asio::ip::tcp::resolver resolver(io);
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(3));
timer.async_wait(boost::bind(&asio_socket::schedule, *job));
// I also have to bind the 3 params: query_, resolver, io
io.run();
这样做,我得到template argument deduction/substitution failed:
实际的错误是:
‘void (rapp::cloud::asio_socket::*)(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::query&, boost::asio::ip::tcp::resolver&, boost::asio::io_service&) aka void (rapp::cloud::asio_socket::*)(boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp>&, boost::asio::ip::basic_resolver<boost::asio::ip::tcp>&, boost::asio::io_service&)’ is not derived from ‘boost::type<R>’
timer.async_wait(boost::bind(&asio_socket::schedule, *job));
如何绑定(多态)共享指针job
的方法schedule
,同时绑定参数?
尝试:
timer.async_wait(boost::bind(&asio_socket::schedule, *job, _1, _2, _3)(&query_, &resolver, &io))
抱怨传递 5 个参数,而候选人期望 2 个参数。
我的猜测是timer.async_wait
想将方法绑定到对象?
-
如何将异步计时器正确绑定到调度操作?
我是否需要进行嵌套绑定,一次用于异步计时器,一次用于计划作业?
【问题讨论】:
【参考方案1】:如果您想将引用传递给bind
,您需要将它们作为reference_wapper<>
传递,您可以使用boost::ref(x)
或boost::cref(x)
。
如果您不这样做,bind
调用将尝试复制它们,这当然不适用于不可复制的 asio
对象。
这样的事情应该可以工作:
timer.async_wait(boost::bind(&asio_socket::schedule,
job, // should bind to a shared_ptr just fine
boost::ref(query_),
boost:;ref(resolver),
boost::ref(io),
boost::placeholders::_1);
时间表需要以下签名:
(boost::asio::ip::tcp::resolver::query &,
boost::asio::ip::tcp::resolver &,
boost::asio::io_service &,
const boost::system::error_code& ec)
因为 async_wait 要求其处理程序能够接受错误代码参数作为其“第一个”未绑定参数。
这就是为什么您必须指定 boost::placeholders::_1 - 将绑定程序中的“第一个”参数(由 bind 创建)编组到类的处理程序方法的第四个参数。
【讨论】:
非常感谢您的帮助。我试过boost::ref
,但我得到了error: invalid use of non-static member function
。所以现在我正在尝试使用boost::mem_fn
和boost::ref
。不过我还是一头雾水,难道我还需要绑定schedule
方法的参数吗?
@Ælex 更新了答案。希望这是有道理的。如果没有,请查看 asio 文档中的示例。
确实有效!非常感谢!我仍然有点困惑,但这是有道理的。我很惊讶它适用于std::shared_ptr
。最后一个问题,占位符是用于job
对象指针,而不是用于对参数的引用?
@Ælex 占位符用于 async_wait 在调用您的处理程序时将提供的参数。它期望调用带有签名 f(const error_code& ec) 的处理程序。占位符允许它向您发送一个参数,然后您将该占位符绑定到处理程序方法的第四个参数中。成员函数的 std::bind 将绑定到指针、shared_ptr 和(从内存中)引用包装器。为了满足大多数用例,bind 有多个重载(std::bind 也是如此,顺便说一下,它也可以用于构造 asio 处理程序)。以上是关于boost::asio::deadline_timer 绑定到多态套接字类指针的主要内容,如果未能解决你的问题,请参考以下文章