【问题标题】:QT Conditional signal emitting - efficiencyQT 条件信号发射 - 效率
【发布时间】:2017-01-10 11:30:54
【问题描述】:

我已经有一个更大的项目和架构,并且遇到了 QT 信号槽系统具有非常同质的信号和问题:1. 要么有许多不同名称的不同信号方法,比如

signals:
sig_1(bool b);
sig_2(bool b);
...
sig_n(bool b);

或: 2. 发出差异作为参数

signal:
sig(uint n, bool b);

让 slot 方法决定 n 是否适合它的内部值

每个选项都比另一个更糟糕:

  1. 很棒的代码,我更喜欢通用解决方案
  2. 每个插槽都必须检查它的编号是否合适,所以每次 O(n) 连接的一行,当 moc 已经通过一个我们可以达到 O(log n) 的开关块时

情况:发射器是一种微控制器抽象,可获知输入变化。许多插槽类只有一个或两个输入连接,需要了解它们的变化。从结构上讲,发射类不应依赖于插槽类,因此不应保留其侦听器列表或包含侦听器的通用超类或接口,这就是我坚持使用信号/插槽系统的原因。

所以我的问题: 在 sig/slot 系统或 moc 中是否有某种扩展或参数,或者我在这里完全错过了什么?

【问题讨论】:

  • 如果您使用 Qt 5 并使用带有函数指针的新语法连接信号和插槽,则应直接调用插槽(无需通过 qt_static_metacall() 及其 switch)。跨度>
  • 感谢本杰明,这让事情变得更糟了,因为现在没有实例,只是直接链接的汇编代码,没有要排序的实例。至少每个听众的检查时间都变短了。
  • 更糟?我不明白。
  • 因为之前至少有一个实例能够将输入映射到输出,所以现在它是硬连线的。在 sig-slot 系统的情况下,这是一个巨大的性能优势。

标签: c++ qt signals-slots qt-signals


【解决方案1】:

Qt 中有一个名为 QSignalMapper 的类可以帮助管理多对一连接,但它并不能完全解决多对多问题

您可以尝试取消直接(发射器-接收器)连接的想法,并尝试在中间使用共享数据向量。只发出一个信号(“数据更新”)。接收者将收到有关更新的通知,并仅从共享数据对象中提取他们需要的数据(如果不考虑线程安全,这可以像映射一样简单)。

如果数据向量很小并且复制起来相对便宜,您可以简单地将整个向量/映射直接发送给每个人(如上所述,在 Qt5 中,直接连接会导致直接函数调用,所以这不会是全部慢)


【讨论】:

    【解决方案2】:

    感谢 d.Candela:多对一、多对多的概念有助于解决问题。我的问题是缺少一对多。解决方案是一个模板化的管理器类,保持一个只有稀疏条目 1 的矩阵。每一行都是输入值的一个位,并且列表示订阅者,列向量作为订阅索引。从这里开始,它只是位移和掩蔽。因此,监听器的插槽由管理器中的模板向量替换,并且信号源连接到管理器。 如果有一个可对角化矩阵的特殊情况(只有单位订阅向量),我们可以保持它的排序并从 O(n) 下降到 O(n^-2)。

    【讨论】:

      【解决方案3】:

      您可以创建一个类来管理所有不同的信号类型,然后在您的信号中发出该类的对象。插槽可以检查发出的对象以查看它们是否需要处理它。示例代码:

      struct SignalInfo {
        string description;
        bool value1;
        int value2;
        //Etc
      };
      

      那么您的信号的签名将是:

      void sig(SignalInfo);
      

      您的插槽可能如下所示:

      void Handle_signal(SignalInfo info) {
        if (info.description == "type 1") {
          /*do something*/
        }
      }
      

      优点是您可以更改SignalInfo 类而无需更改任何其他内容。话虽如此,您可以改为发出和接收对SignalInfo 对象的引用,这将让您继承SignalInfo 以获得更大的灵活性。示例信号和槽签名将是:

      void sig(SignalInfo&);
      
      void Handle_signal(SignalInfo& info);
      

      【讨论】:

      • 这仍然不是解决方案,因为阻止接收器操作的代码仍然在接收器端。这是我提出的第二个选项,带有描述的陷阱。我想事先避免接收者插槽调用,因为大多数时候他们都在第一行返回。我没有遇到不同信号类型但不同信号参数值的问题,并且想要基于这些不同信号参数值的连接机制。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多