简体   繁体   English

QT条件信号发射-效率

[英]QT Conditional signal emitting - efficiency

I allready have a bigger project and architecture and run into a situation with the QT signal-slot system with very homogenous signals and the problem: 1. Either many different signal mehtods with different names like 我已经准备了一个更大的项目和体系结构,并遇到了QT信号槽系统的情况,该系统的信号非常同质,而且存在以下问题:1.可能有许多不同的信号方法,例如名称不同

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

or: 2. emiting the difference as argument 或者:2.发出差异作为参数

signal:
sig(uint n, bool b);

and lets the slot method decide if n fits it's internal values 并让slot方法决定n是否适合其内部值

each options is worse that the other: 每个选项比另一个更糟:

  1. awefull code, I would prefer more like a generic solution 很棒的代码,我更喜欢通用解决方案
  2. every slot has to check if it number will fit, so a row of everytime O(n) connections, when the moc allready goes through a switch-block where we can reach O(log n) 每个插槽都必须检查它的数量是否合适,因此,每隔O(n)个连接,当moc都经过一个交换块时,我们就可以到达O(log n)

The situation: the emitter is a microcontroller-abstraction and gets informed on input changes. 这种情况:发射器是微控制器的抽象,并在输入变化时得到通知。 Many of the slot-classes just have one or two inputs connected and need to be informed about their changes. 许多插槽类仅连接一个或两个输入,并且需要通知其更改。 Structurally the emitting class should not depend on the slot-classes and therefore should not keep a list of it's listener or include a common super-class or interface of the listeners, so thats why I'm stick to the signal/slot system. 从结构上讲,发射类不应依赖于插槽类,因此不应保留其侦听器列表,也不应包含侦听器的公共超类或接口,因此这就是为什么我坚持使用信号/插槽系统。

So my Question: Is there some kind of extension or argument in the sig/slot system or to the moc or have I missed something completely here? 所以我的问题是:信号/槽位系统或Moc中是否存在某种扩展名或参数,或者我在这里完全错过了什么?

there is a class in Qt called QSignalMapper that helps managing Many-to-One connections, but afaik it doesn't qutomatically solve a Many-to-Many problem Qt中有一个叫做QSignalMapper的类,可以帮助管理多对一连接,但是afaik并不能从数学上解决多对多问题。

You could try doing away with the idea of direct (emitter-receiver) connections, and try using a shared data vector in the middle. 您可以尝试取消直接(发射器-接收器)连接的想法,并尝试在中间使用共享数据向量。 Emit only one signal ("data updated"). 仅发射一个信号(“数据已更新”)。 Receivers will get notified about the update, and pull only the data they need from the shared data object (this can be as simple as a map if thread safety is not a concern). 接收者将收到有关更新的通知,并仅从共享数据对象中提取所需的数据(如果不考虑线程安全性,这可以像映射一样简单)。

If the data vector is small and relatively cheap to copy, you could simply emit the whole vector/map directly to everyone (as noted above, in Qt5 direct connections result in direct function calls, so this won't be all that slow) 如果数据向量较小且复制相对便宜,则可以直接将整个向量/映射直接发送给所有人(如上所述,在Qt5中,直接连接会导致直接函数调用,因此不会太慢)


Thanks to d.Candela: The Concept of Many-to-One, Many to Many helps a little bit to sort the Problem. 感谢d.Candela:多对一,多对多的概念对解决问题有一点帮助。 My Problem was the missing One-to-Many. 我的问题是缺少一对多。 The solution is a templated manager-class, keeping a matrix with only sparse entries of 1. Every row is a bit of the input value, and the colums are representing the subscribers with the column-vector as their subscription-index. 该解决方案是模板化的管理器类,仅保留一个稀疏条目为1的矩阵。每一行都是输入值的一部分,并且列以列向量作为订阅者索引来表示订阅者。 From here it is just bit shifting and masking. 从这里开始只是移位和屏蔽。 So the slots of the listeners are relaced by a templated vector in the manager and the signal source is connected to the manager. 因此,管理器中的模板化矢量取代了监听器的插槽,并且信号源已连接到管理器。 If there is a special case of a diagonalizable matrix (only unit subscription vectors) we can keep it sorted and go down to O(n^-2) from O(n). 如果存在对角化矩阵的特殊情况(仅单位订购向量),我们可以对其进行排序,然后从O(n)降到O(n ^ -2)。

You could create a class for managing all your different signal types, then emit objects of that class in your signals. 您可以创建一个类来管理所有不同的信号类型,然后在信号中发出该类的对象。 Slots can examine the emitted object to see if they need to process it. 插槽可以检查发射的对象,以查看是否需要对其进行处理。 Example code: 示例代码:

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

Then the signature of your signal would be: 那么您的信号签名将是:

void sig(SignalInfo);

and your slots might look like this: 并且您的广告位可能如下所示:

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

The advantage is that you can change the SignalInfo class without needing to change anything else. 好处是您可以更改SignalInfo类,而无需更改其他任何内容。 With that said, you could instead emit and receive references to SignalInfo objects, which would let you subclass SignalInfo for even more flexibility. 话虽如此,您可以改为发出和接收对SignalInfo对象的引用 ,这将使您可以SignalInfo的子类, SignalInfo获得更大的灵活性。 Example signal and slot signatures would be: 示例信号和插槽签名为:

void sig(SignalInfo&);

void Handle_signal(SignalInfo& info);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM