如何取消boost asio io_service帖子
How to cancel boost asio io_service post
如何取消已发布的回调:
getIoService()->post(boost::bind(&MyClass::myCallback, this));
并保持其他发布的回调不受影响?
问题是,我有一些对象从不同的线程接收事件,并将它们发布到ioservice,以便处理主线程中的事件。如果在某个时候我想删除我的对象,ioservice会尝试在销毁的对象中执行已经发布的回调。在这种情况下,我不能在对象中存储任何标志,因为它将被删除。
有一种可能的解决方案可以使用enable_shared_from_this
和shared_from_this()
,但不知道是否有其他解决方案。
感谢
正如Sam所回答的,不可能选择性地取消已发布的处理程序。
如果目标是防止对生存期已过期的对象调用成员函数,那么使用enable_shared_from_this
是惯用的解决方案。这种方法的一个结果是,对象的生存期至少延长到处理程序的生存期。如果对象的析构函数可以延迟,那么可以考虑通过shared_from_this()
将对象绑定到处理程序。
另一方面,如果销毁需要立即进行,那么考虑编写一个弱绑定到实例的函子。这个问题讨论了与weak_ptr
的绑定,并提供了一些研究/讨论链接。以下是弱绑定到对象的函子的简化完整示例:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
/// @brief Mocked up type.
class MyClass:
public boost::enable_shared_from_this<MyClass>
{
public:
MyClass() { std::cout << "MyClass()" << std::endl; }
~MyClass() { std::cout << "~MyClass()" << std::endl; }
void action() { std::cout << "MyClass::action()" << std::endl; }
};
/// @brief weak_binder is a functor that binds a member function
/// to a weakly managed object instance. I.e. this
/// functor will not extend the life of the instance to
/// which it has been bound.
template <typename Fn,
typename C>
struct weak_binder
{
private:
typedef typename C::element_type element_type;
public:
/// @brief Constructor.
weak_binder(Fn& fn, C& c) : fn_(fn), c_(c)
{}
/// @brief Conditional invoke Fn if C still exists.
void operator()()
{
std::cout << "weak_binder::operator()" << std::endl;
// Create a shared pointer from the weak pointer. If
// succesful, then the object is still alive.
if (boost::shared_ptr<element_type> ptr = c_.lock())
{
// Invoke the function on the object.
(*ptr.*fn_)();
}
}
private:
Fn fn_;
boost::weak_ptr<element_type> c_;
};
/// @brief Helper function to create a functor that weakly
/// binds to a shared object.
template <typename Fn,
typename C>
weak_binder<Fn, C> weak_bind(Fn fn, C c)
{
return weak_binder<Fn, C>(fn, c);
}
int main()
{
boost::asio::io_service io_service;
boost::shared_ptr<MyClass> my_class = boost::make_shared<MyClass>();
// my_class will remain alive for this handler because a shared_ptr
// is bound to handler B, and handler B will only be destroyed after
// handler A has been destroyed.
io_service.post(weak_bind(&MyClass::action,
my_class->shared_from_this())); // A
// my_class will remain alive for this handler because it is bound
// via a shared_ptr.
io_service.post(boost::bind(&MyClass::action,
my_class->shared_from_this())); // B
// my_class will not be alive for this handler, because B will have
// been destroyed, and the my_class is reset before invoking the
// io_service.
io_service.post(weak_bind(&MyClass::action,
my_class->shared_from_this())); // C
// Reset the shared_ptr, resulting in the only remaining shared_ptr
// instance for my_class residing within handler B.
my_class.reset();
io_service.run();
}
结果输出:
MyClass()weak_binder::运算符()MyClass::action()MyClass::action()~MyClass()weak_binder::operator()
可以看出,MyClass::action()
只被调用两次:一次是在实例处于活动状态时通过weak_binder
调用(处理程序A),另一次是通过boost::bind
调用,其中实例通过shared_ptr
维护(处理程序B)。处理程序C被调用,但weak_binder::operator()
检测到实例已被破坏,导致静默的no-op。
您不能通过io_service
以这种方式选择性地取消回调。一种选择是将逻辑移动到更高的级别,例如MyClass
内部。示例实现可能是:
class MyClass : public boost::enable_shared_from_this<MyClass>
{
public:
typedef boost::shared_ptr<MyClas> Ptr;
static Ptr create( boost::asio::io_service& io_service ) {
const Ptr result( new MyClass );
io_service.post( boost::bind(&MyClass::myCallback, result) );
return result;
}
void myCallback() {
if ( _canceled ) return;
}
void cancel() { _canceled = true; }
private:
MyClass() : _canceled(false) { }
private:
bool _canceled;
};
该类使用boost::shared_ptr
来强制执行共享所有权语义。这样做可以确保只要回调在调度之前保留在io_service
队列中,对象的生存期就会持续。
- 理解boost::asio-async_read在无需读取内容时的行为
- Seg Fault Issue C++ (file IO / getline)
- 提升 ASIO 无法识别计时器对象
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 为什么在读取文件大小时文件IO速度会发生变化
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost::asio如何生成多个协同程序,然后加入它们
- 缓慢提升ASIO
- 从 Boost ASIO 获取 epoll 描述符 io_service对象
- 如何在 Boost.Asio 中使用 Zero-copy sendmsg/receive
- C++ Boost::asio串行通信与Arduino无法写入
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- ASIO signal_set多个 IO 线程不可靠,具体取决于代码顺序?
- ASIO IO完成回调订单与实际IO操作的顺序
- boost asio自定义分配器处理程序io服务编译后错误
- 如何为 Boost.Asio 设计自定义 IO 对象
- Boost asio:io服务在销毁步骤中被阻止了更多的处理程序问题
- 将System.IO.Ports.SerialPort代码转换为boost::asio
- boost::asio::io_service:在等待将来时将控制权返回到 IO 服务的运行