如何让一个C ++的boost ::信号从密封发射它的对象的对象捕捉?(How to make a

2019-09-16 12:51发布

我有一个TcpDevice类它封装TCP连接,其具有每当远端挂断它获取称为onRemoteDisconnect方法。 然后,有其产生其中采取TcpDevice作为通信信道TcpSession目的和将它们插入在应用程序以使用内部指针容器SessionManager对象。 在任何情况下的管理TcpSessions应该结束,我想SessionManager实例被通知,然后从容器中取出相应的会话,释放与它相关的资源。

我发现我的问题是非常相似,这一问题:

从对象中删除容器本身

但由于他对检查连接状态的线程,它会从我的,我打算使用boost ::信号来解决问题的方法略有不同,所以我决定去对待它面向一个新的问题-我道歉,如果这是错误的方式做到这一点...我仍然得到关于如何正确使用SO的感觉:)

因为我有点熟悉QT的信号/插槽,我发现的boost ::信号提供了一个类似的机制(我已经使用boost :: ASIO和在这个项目中没有QT),所以我决定实施remoteDeviceDisconnected信号由TcpDevice的 onRemoteDisconnect发射,以及用于我将具有在SessionManager的狭槽,然后这将删除从容器中断开的会话和设备。

最初尝试一下我声明了信号TcpDevicetcpdevice.hpp公共成员:

class TcpDevice
{
             (...)
  public:
    boost::signal <void ()> remoteDeviceDisconnected;
             (...)
}

然后我发出从TcpDevice的这样onRemoteDisconnect方法:

remoteDeviceDisconnected();

现在,有什么办法这个信号连接到由会话管理器我SessionManager插槽? 我尝试这样做:

unsigned int SessionManager::createSession(TcpDevice* device)
{
  unsigned int session_id = session_counter++;
  boost::mutex::scoped_lock lock(sessions_mutex);
  sessions.push_back(new TcpSession(device, session_id));
  device->remoteDeviceDisconnected.connect(boost::bind(&SessionManager::removeDeadSessionSlot, this));
  return session_id;
}

它编译罚款,但在链接时,报告说在几个目标代码文件remoteDeviceDisconnected的多个定义:

tcpsession.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
sessionmanager.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here

我发现这个奇怪的,因为我没有任何地方重新定义的信号,而只是用它在上面了createSession方法。

任何提示将非常感谢! 谢谢!

Answer 1:

我的错! 就像大家都应该想到,链接是对的。确实有第二个定义,我只是不能发现它的时候了,因为它不是由我的任何类的定义,而只是“浮动”的一个我身边.cpp文件,就像那些上找到的boost ::信号的例子 。

只是为了记录在案,最初的想法工作就像一个魅力:当给定TcpDevice会从远端断开时,它发出的信号remoteDeviceDisconnected,然后由持有指向该TcpDeviceTcpSession实例SessionManager对象捕获。 一旦接到通知,SessionManager的方法removeDeadSessionSlot得到执行,通过ptr_list容器和取出其中一个是断开的会话迭代:

void SessionManager::removeDeadSessionSlot()
{
  boost::mutex::scoped_lock lock(sessions_mutex);
  TcpSession_ptr_list_it it = sessions.begin();
  while (it != sessions.end()) {
    if (!(*it).device->isConnected())
      it = sessions.erase(it);
    else
      ++it;
  }
}

希望可以作为给别人参考!



文章来源: How to make a C++ boost::signal be caught from an object which encapsulates the object which emits it?