Can someone suggest to me the best practice for the following use case:
I have a QObject class with signals that live in the main thread, for example
class Motor : public QObject
{
Q_OBJECT
Q_PROPERTY(int speed READ speed NOTIFY speedChanged FINAL)
friend class Plc;
public:
explicit Motor(QObject *parent = nullptr) :
QObject{ parent }
{}
int speed() const { return m_speed; }
signals:
void speedChanged();
protected:
void setSpeed(int speed) {
if(m_speed == speed)
return;
m_speed = speed:
emit speedChanged();
}
private:
int m_speed = 0;
};
The setter is defined as protected because I want that the main program can only read the value.
Only friend class Plc
can write it.
Plc
class is running on a different thread. It reads data coming from a PLC and update the Motor
class.
Below an example of the main thread event loop
void MainWindow::MainWindow()
{
m_plc = new Plc();
connect(this, &MainWindow::triggerRead, m_plc, &Plc::readPlcData);
connect(m_plc , &Plc::readCompleted, this, &MainWindow::processData);
m_plc->setResource(&m_motor);
m_plcThread = new QThread(this);
m_plc->moveToThread(m_plcThread);
connect(m_plcThread, &QThread::started, m_plc, &Plc::readPlcData);
thread->start();
}
void processData()
{
// Limiting the motor speed
if(m_motor.speed() > 20)
plc->writeMotorSpeed(20); // Write data into PLC only. Next read will update motor.speed value
// Do other stuff
emit triggerRead();
}
Below an exaple of Plc
class
class Plc : public QObject
{
Plc() : QObject{ nullptr }
{
connect(this, &Plc::readPlcData, this, &Plc::doReadData);
}
void setResource(Motor *motorPtr) { m_motor = motorPtr; }
signals:
void readPlcData();
void readCompleted(QPrivateSingal);
private:
void doReadData()
{
// Reding data from PLC
if(m_motor) {
m_motor->setSpeed(data[0]);
}
emit readCompleted(QPrivateSingal());
}
private:
Motor *m_motor = nullptr;
};
In this scenario, is “impossible” that the Plc
class is updating a Motor
value meanwhile the main thread is reading it.
The same if I’ve exposed the Motor
class to QML for display some Q_PROPERTY.
The UI has some buttons that if clicked, the main thread checks some Motor
‘s values. In this case, I suppose that there is the risk that Plc
class is updating values while the main thread is reading it. It’s right?
If the latter is true, is better to protect the Motor
class with a mutex that protects the reading and writing of the class, right?