Merging multiple signals into one
-
Hi. There is a device which I get multiple kinds of realtime data from it:
class Device { signals: void param1Changed(Param1 p); void param2Changed(Param2 p); ... };
Those
Param1
,Param2
etc. are independent values read from device.
But sometimes I need to get multiple values at once and do a calculation:QObject *contextObject0 = new QObject; connect(d, Device::param1Changed, contextObject0, [=](Param1 p1) { QObject *contextObject1 = new QObject; connect(d, Device::param2Changed, contextObject1, [=](Param2 p2) { // do something with p1 and p2 values contextObject0->deleteLater(); contextObject1->deleteLater(); }); });
This can be even more cumbersome and clumsy when more than 2 parameters are needed and I should add another lambda inside the above one.
Is there a generic solution to this? I mean setting multiple signals to it (in constructor, via setter, etc.), and get a unified signal which is emitted when all of them are emitted some time age (obviously with most recent values)
Even a predefined and hardcoded signal signature is good enough for me, for now :-)Thanks
-
Hi. There is a device which I get multiple kinds of realtime data from it:
class Device { signals: void param1Changed(Param1 p); void param2Changed(Param2 p); ... };
Those
Param1
,Param2
etc. are independent values read from device.
But sometimes I need to get multiple values at once and do a calculation:QObject *contextObject0 = new QObject; connect(d, Device::param1Changed, contextObject0, [=](Param1 p1) { QObject *contextObject1 = new QObject; connect(d, Device::param2Changed, contextObject1, [=](Param2 p2) { // do something with p1 and p2 values contextObject0->deleteLater(); contextObject1->deleteLater(); }); });
This can be even more cumbersome and clumsy when more than 2 parameters are needed and I should add another lambda inside the above one.
Is there a generic solution to this? I mean setting multiple signals to it (in constructor, via setter, etc.), and get a unified signal which is emitted when all of them are emitted some time age (obviously with most recent values)
Even a predefined and hardcoded signal signature is good enough for me, for now :-)Thanks
This post is deleted! -
@MajidKamali Your way of calling connect statement is confusing/not correct, in the first connect statement Device::param1Changed lambda slot you are creating second connection Device::param2Changed.
Which means you are doing multiple connection for each time the Device::param1Changed signal is emitted.One approach can be as follows,
1)Have dirty bit flag for the data, indicating value changed.
2)create the function which tracks the dirty bit flag for the data and emits the processing signal if both(param1 & Param2 dirty bit) are set.
3)connect the param1changed/param2changed from device signal to the slot and store the data in the class. and set dirty bit flag for the data.
call the dirtybit tracker function
4)in the processing function after the processing reset the dirty bit -
I would argue that if it is truly a "device" you are reading from then you should NOT use a device class an associated signals from that class at all. Reason being is that you are making the interface way too specialized and specific.
-
@Kent-Dorfman You are right.
Device
class is actually an interface to a 'real' device class.
@nagesh Oh I didn't noticed about multiple connections in lambda. Thanks. But I didn't understand your solution yet. By 1, you mean instead of emittingparam1Change(Param p)
signal, emit aparam1Dirty()
signal and save a dirty bit flag instead of real value? And then in 2, check for desired values (dirty bit flags) and emit a unified signal? -
@Kent-Dorfman You are right.
Device
class is actually an interface to a 'real' device class.
@nagesh Oh I didn't noticed about multiple connections in lambda. Thanks. But I didn't understand your solution yet. By 1, you mean instead of emittingparam1Change(Param p)
signal, emit aparam1Dirty()
signal and save a dirty bit flag instead of real value? And then in 2, check for desired values (dirty bit flags) and emit a unified signal?@MajidKamali
some sample code snippet what I was proposing..//Intermediate storage of Data & state struct Data { bool isParam1Set=false; Param1 param1; bool isParam2Set=false; Param1 param2; }; Data paramsData; connect(d, Device::param1Changed,this,[this](int param1){ paramsData.isParam1Set =true; paramsData.param1 = param1; this->paramTracker(); }); connect(d, Device::param1Changed,this,[this](int param2){ paramsData.isParam1Set =true; paramsData.param2 = param2; this->paramTracker(); }); void paramTracker() { if( paramsData.bParam1Set && paramsData.bParam2Set ) { emit paramsChanged(paramsData.param1, paramsData.param2); paramsData.isParam1Set = false; paramsData.isParam2Set = false; } }
-
@nagesh Thanks that's very useful