强制删除 boost::signals2 中的槽

2024-02-01

我发现 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.

Command 类通过获取一个使用 boost::bind 绑定到 ActualWorker 信号的 Shared_ptr 来保持自身的活动。

当工作程序完成时,将调用 Command 中的处理程序。现在,由于我希望销毁 Command 对象,因此我断开了与信号的连接,如上面的代码所示。问题是,实际的槽对象在断开连接时不会被删除,它只是被标记为无效,然后在稍后删除。这反过来似乎取决于再次触发的信号,但在我的情况下它不会这样做,导致插槽永远不会过期。因此 boost::bind 对象永远不会超出范围,将一个永远不会被删除的对象保存到我的对象中。

我可以通过使用 this 指针而不是共享指针进行绑定,然后使用成员共享指针使对象保持活动状态来解决此问题,然后在处理程序函数中释放该成员,但这会让设计感觉有点过于复杂。有没有办法强制 Signal2 在断开连接时删除插槽?或者我还可以做些什么来简化设计?

任何评论表示赞赏!


boost::signals2在连接/调用期间清理插槽。

因此,如果所有插槽都断开与信号的连接,第二次调用信号将不会调用任何内容,但它应该清理插槽。

要回答您的评论,是的,如果有其他连接的插槽,再次调用信号是不安全的,因为它们将被再次调用。在这种情况下,我建议您采取相反的方式并连接一个虚拟插槽,然后在调用“真实”插槽时断开它。连接另一个插槽将清除过时的连接,因此您的插槽应该被释放。

只需确保您没有在虚拟插槽中保留任何需要释放的引用,否则您将回到开始的地方。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强制删除 boost::signals2 中的槽 的相关文章

随机推荐

  • 正则表达式和 unicode

    我有一个脚本可以解析电视剧集的文件名 例如 show name s01e02 avi 获取剧集名称 来自 www thetvdb com API 并自动将它们重命名为更好的名称 节目名称 01x02 avi 该脚本工作正常 直到您尝试在具有
  • 检查 URL 是否有 http:// 前缀

    在我的应用程序中 当用户添加对象时 还可以添加该对象的链接 然后可以在 webView 中打开该链接 我尝试保存不带 http 前缀的链接 然后在 webView 中打开它 但无法打开它 在webView开始加载之前 有没有办法检查保存的U
  • 在 Dart 中发送 SMTP 电子邮件

    我查看了 API 文档和语言指南 但没有看到任何有关在 Dart 中发送电子邮件的内容 我也检查了这个谷歌群组帖子 https groups google com a dartlang org forum topic misc 5YNvrm
  • 如何通过 JSON 文件为curl 传递有效负载?

    我可以通过以下方式成功创建一个地方curl执行以下命令 curl vX POST https server api v1 places json d auth token B8dsbz4HExMskqUa6Qhn place name Fu
  • 为复杂的跨平台程序创建安装程序

    我正在为一堆相对复杂的桌面应用程序绘制一个应用程序部署过程 我们有本机应用程序和 Java 应用程序 因此部署必须能够检查 JRE 是否存在并在需要时安装它 某些应用程序依赖于特殊硬件 因此部署还必须能够启动必要的驱动程序安装程序 一些应用
  • 使用 AsyncTask 时应用程序挂起并暂停所有线程

    我正在尝试使用AsyncTask类来获取网站的内容 logcat 告诉我W art Suspending all threads took 15 or any other number ms反复 我的应用程序被冻结 直到日志消息打印完成 日
  • 在 Powershell 中设置 InheritanceFlags 与 PropagationFlags

    我正在尝试找到 InheritanceFlags 和 PropagationFlags 的正确组合 以便我的新文件夹不会继承之前文件夹的权限 而是将权限传播到新文件夹中包含的文件夹 文件 我尝试交换我下面有两个 但这只给了新文件夹与上面的文
  • 将三个不同的列合并为 R 中的日期

    现在 我在 R 的数据文件中有 3 个单独的列 分别为年 月和日 如何将这三列合并为一列并使 R 理解它是日期 这是现在的样子 year mon day gnp 1947 1 1 238 1 1947 4 1 241 5 1947 7 1
  • Elasticsearch 在显示 t: failed to read local state , exiting 后崩溃

    我是 Elasticsearch 的新手 我在本地只运行一个节点 到目前为止 它运行良好 现在一启动就崩溃了 错误堆栈如下 C MyApps elasticsearch6 5 1 elasticsearch oss 6 5 1 elasti
  • 在 bash 中从占据终端整个宽度的破折号字符绘制一条水平线

    我需要一个命令来在终端中绘制一条水平 线 该线必须恰好等于终端长的宽度 无论当前终端宽度如何 并且由破折号字符组成 尽管也可以使用水平线的 unicode 符号 如果能上色就更好了 我需要像这样使用它 echo some text draw
  • WCF:OperationContext.IncomingMessageProperties.Via 返回错误的 URI

    我在 IIS 中托管 WCF 服务 我在 IIS 中为该站点设置了多个主机名绑定 但是 当向任何非默认绑定发出请求时 OperationContext IncomingMessageProperties Via 属性不会报告正确的 url
  • 如何加载共享库而不加载其依赖项?

    说我有一个图书馆libfoo so 1 这取决于 根据ldd on libbar so 1 然而 libbar so 1目前不可用 我的应用程序需要调用一个函数libfoo so 1这不需要libbar so 1 at all 有没有办法加
  • 局部变量的内存可以在其作用域之外访问吗?

    我有以下代码 include
  • 使用Servlet API,如何确定请求是HTTP/1.0还是HTTP/1.1?

    我正在修复一个错误 该错误仅在客户端使用 HTTP 1 0 并且是在防火墙后面秘密地进行 Internet Explorer 代理 时才会显现出来 详细信息在这里 https issues apache org jira browse TA
  • 获取日期中的小时和分钟 (HH:MM)

    我只想得到hh mm从日期 我怎样才能得到这个 我已经尝试过这个 CONVERT VARCHAR 8 getdate 108 只需使用前 5 个字符 SELECT CONVERT VARCHAR 5 getdate 108
  • 在 Java 中,在被调用方法之前和之后运行方法

    我正在尝试编写一个 Java 程序 以便在调用方法A 首先是一个名为methodBeforeA 被调用 然后方法A 执行后 另一个方法被调用命名 方法AfterA 这与 Junit 使用注释 使用 Before Test After 所做的
  • python mechanize 处理两个同名参数

    我正在登录一个页面 其中奇怪地有一个名为的表单输入login email和两个表单输入称为login password 我需要设置两者的值 但直接调用form login password 抛出错误 File Library Python
  • 将整数向量转换为 0 到 1 之间浮点数的最快精确方法

    考虑一个随机生成的 m256i向量 有没有更快 更精确的方法将它们转换为 m256之间的浮点数向量0 包括在内 和1 仅 比除以float 1ull lt lt 32 这是我到目前为止所尝试过的 其中iRand是输入和ans是输出 cons
  • 当线程“等待”某些东西时会发生什么

    When an async method awaits a Task当前正在运行的线程会发生什么 我推测 在 UI 线程上 消息循环将恢复 而在线程池线程上 线程将被释放回线程池 但是如果手动启动线程会发生什么呢 还有其他类型的线程吗 我花
  • 强制删除 boost::signals2 中的槽

    我发现 boost signals2 使用某种连接槽的惰性删除 这使得很难使用连接来管理对象的生命周期 我正在寻找一种方法来强制在断开连接时直接删除插槽 任何有关如何通过以不同方式设计我的代码来解决问题的想法也将受到赞赏 这是我的场景 我有