我发现boost :: signals2使用了一种连接插槽的懒惰删除,这使得使用连接作为管理对象生命周期的东西变得困难.我正在寻找一种方法来强制插槽在断开连接时被直接删除.任何关于如何通过设计我的代码来解决问题的想法也不胜感激!
这是我的场景:我有一个Command类负责做异常需要时间的东西,看起来像这样(简化):
class ActualWorker { public: boost::signals2<void ()> OnWorkComplete; }; class Command : boost::enable_shared_from_this<Command> { public: ... void Execute() { m_WorkerConnection = m_MyWorker.OnWorkDone.connect(boost::bind(&Command::Handle_OnWorkComplete,shared_from_this()); // launch asynchronous work here and return } boost::signals2<void ()> OnComplete; private: void Handle_OnWorkComplete() { // get a shared_ptr to ourselves to make sure that we live through // this function but don't keep ourselves alive if an exception occurs. shared_ptr<Command> me = shared_from_this(); // Disconnect from the signal,ideally deleting the slot object m_WorkerConnection.disconnect(); OnComplete(); // the shared_ptr now goes out of scope,ideally deleting this } ActualWorker m_MyWorker; boost::signals2::connection m_WorkerConnection; };
这个类是这样调用的:
... boost::shared_ptr<Command> cmd(new Command); cmd->OnComplete.connect( foo ); cmd->Execute(); // now go do something else,forget all about the cmd variable etcetera.
通过将shared_ptr绑定到使用boost :: bind绑定到ActualWorker信号的命令类来保持本身的生存.
当工作人员完成时,调用Command中的处理程序.现在,由于我希望Command对象被销毁,所以我断开了与上面代码中可以看到的信号.问题是实际的插槽对象在断开连接时不会被删除,它只被标记为无效,然后在以后删除.这反过来似乎取决于再次发射的信号,这在我的情况下不会做,导致插槽永远不会过期.因此,boost :: bind对象永远不会超出范围,将shared_ptr保存到我的对象,永远不会被删除.
我可以通过使用这个指针而不是一个shared_ptr绑定来解决这个问题,然后使用一个成员shared_ptr保持我的对象,然后我在处理函数中释放它,但是这样会使得设计感觉有些过于复杂.断开连接时是否有办法强制signal2删除插槽?还有还有什么可以做的,以简化设计?
任何意见都赞赏!