Question about QThread and how thread work in general.
-
Hello,
I'm working on a project where two different class are working together: a class that is taking care of multiple smart servo and another one that is receiving and sending feedback from and to a computer.
The second class, that I will named the command class, is receiving the instruction for the servo and setting these in another class that I will named the instruction class.
The first class, that I will named the servo class, is a kind of loop in which one there three function: first one is reading the instruction class and deal with thew position, speed and acceleration of the smart servo, the second one is asking the servo status, in order to write them in the instruction class, and the last one is emitting some signal if there is a catastrophic issue with these servo.
I need these two class to work together and concurrently. To do so, I planned to make these two classes inherit from QThread and not synchronized them. That way, the servo class would run a constant diagnostic of the servo while being able to set the the position of the servo and the command class would constantly being able to receive command and interpret them, without slowing the servo class.
From what I understand of thread in general, two thread would be give an illusion having two part of the program that are executed simultaneously, but I'm relatively inexperienced with thread. Is this a correct use of thread, or would that make my program worst that if I was not using thread?
-
Hello,
I'm working on a project where two different class are working together: a class that is taking care of multiple smart servo and another one that is receiving and sending feedback from and to a computer.
The second class, that I will named the command class, is receiving the instruction for the servo and setting these in another class that I will named the instruction class.
The first class, that I will named the servo class, is a kind of loop in which one there three function: first one is reading the instruction class and deal with thew position, speed and acceleration of the smart servo, the second one is asking the servo status, in order to write them in the instruction class, and the last one is emitting some signal if there is a catastrophic issue with these servo.
I need these two class to work together and concurrently. To do so, I planned to make these two classes inherit from QThread and not synchronized them. That way, the servo class would run a constant diagnostic of the servo while being able to set the the position of the servo and the command class would constantly being able to receive command and interpret them, without slowing the servo class.
From what I understand of thread in general, two thread would be give an illusion having two part of the program that are executed simultaneously, but I'm relatively inexperienced with thread. Is this a correct use of thread, or would that make my program worst that if I was not using thread?
@Factao
Hi,
as @J.Hilk suggested to me I suggest to read:take a look here
https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/and here
https://doc.qt.io/qt-5/qthread.html#detailson how to properly do threading in Qt.
PS: see my original post: https://forum.qt.io/topic/99973/qthread-msleep-doesn-t-work-when-system-time-is-changed
-
Hi,
That 2011 blog entry has been followed by:
https://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html
-
Thanks for these reply!
If I understand, the two class need to inherit from QObject, then I create a QThread for one of them, I move the QObject in the thread, then run the thread, so one of them is doing its thing in the thread while the other is doing its own in the main.
From what I've read, they need to communicate with signal and slot, but the worker class is not supposed to directly interact with the commanding class, just discretely updating the virtual model of the servo motor. The commanding class may directly used the worker class to do an action, and I was planning using pointer for that. Is it possible to simply giving them a pointer to the other and having them indirectly interacting even if they are in two different thread?
-
Thanks for these reply!
If I understand, the two class need to inherit from QObject, then I create a QThread for one of them, I move the QObject in the thread, then run the thread, so one of them is doing its thing in the thread while the other is doing its own in the main.
From what I've read, they need to communicate with signal and slot, but the worker class is not supposed to directly interact with the commanding class, just discretely updating the virtual model of the servo motor. The commanding class may directly used the worker class to do an action, and I was planning using pointer for that. Is it possible to simply giving them a pointer to the other and having them indirectly interacting even if they are in two different thread?
@Factao
Hi,
I’m not sure I understand well your problem, don’t worry it is fault of my English :(
You have two ways to synchronize between threads:- Signal&Slot
- Direct synchronization (with a pointer)
I suggest to read:
https://doc.qt.io/qt-5/threads-synchronizing.htmlhttps://doc.qt.io/qt-5/threads-qobject.html
I hope I explained well what you want to know
Regards
-
@Factao
Hi,
I’m not sure I understand well your problem, don’t worry it is fault of my English :(
You have two ways to synchronize between threads:- Signal&Slot
- Direct synchronization (with a pointer)
I suggest to read:
https://doc.qt.io/qt-5/threads-synchronizing.htmlhttps://doc.qt.io/qt-5/threads-qobject.html
I hope I explained well what you want to know
Regards
@CP71
Hi,
Basically, I have two class that inherits from QObject, one of them is on the main and the other is on a thread. They both contain a pointer to the other and used this pointer to read an change their values. I think it might be this direct synchronisation you are talking about.
My question is: Could this method have default that could result in a crash or any other thing that may make the application having some unexpected feature?ps: Don't worry, your I'm not an english native neither and I perfectly understand what you are saying.
-
For simply sending data between the main GUI thread and a worker thread the signal/slot mechanism is the safer alternative, as it is well tested and simple to use. Unless there are near real-time requirements of syncronization then that's the route I'd recommend.
-
@CP71
Hi,
Basically, I have two class that inherits from QObject, one of them is on the main and the other is on a thread. They both contain a pointer to the other and used this pointer to read an change their values. I think it might be this direct synchronisation you are talking about.
My question is: Could this method have default that could result in a crash or any other thing that may make the application having some unexpected feature?ps: Don't worry, your I'm not an english native neither and I perfectly understand what you are saying.
@Factao if you really want to pass objects/data/pointers between threads and allow them to modify/read the data, than you'll have too look into
QMutex
-
@J.Hilk said in Question about QThread and how thread work in general.:
if you really want to pass objects/data/pointers between threads and allow them to modify/read the data, than you'll have too look into
pass objects, or share objects? if the objects are shared then yes, the mutex/semaphore would be required, but if the objects are passed (copied) then signal/slot would be adequate, right?
-
@J.Hilk said in Question about QThread and how thread work in general.:
if you really want to pass objects/data/pointers between threads and allow them to modify/read the data, than you'll have too look into
pass objects, or share objects? if the objects are shared then yes, the mutex/semaphore would be required, but if the objects are passed (copied) then signal/slot would be adequate, right?
@Kent-Dorfman well yes, I wrote
objects/data/pointers
and meant to writeobjects/data - pointers
;-) -
@Factao if you really want to pass objects/data/pointers between threads and allow them to modify/read the data, than you'll have too look into
QMutex
@J.Hilk Interesting, but after looking QMutex, I have one quesition: If I'm locking a variable within a thread, may other thread "read" it? Within the docs, the following sentence does not specifiy that: "Then only one thread can modify number...". (after the example within the QMutex class). If I don't need to modify this value, then thread should not have any difficulties to read a variable that only one thread is modifying.
@Kent-Dorfman Yes, I need a near real-time synchronisation, so I can't use too many signals or slots.
-
@Factao said in Question about QThread and how thread work in general.:
If I'm locking a variable within a thread, may other thread "read" it?
Multithreaded reads are only consistent on atomic data items. IOW, ordinal variables that can be read or written with a single processor native instruction. You have no way of guaranteeing when a context switch will occur, so values of more complex variables are undefined unless you guard their access with a critical section lock (ie semaphore/mutex)
-
@Factao said in Question about QThread and how thread work in general.:
If I'm locking a variable within a thread, may other thread "read" it?
Multithreaded reads are only consistent on atomic data items. IOW, ordinal variables that can be read or written with a single processor native instruction. You have no way of guaranteeing when a context switch will occur, so values of more complex variables are undefined unless you guard their access with a critical section lock (ie semaphore/mutex)
@Kent-Dorfman I'm not really sure to understand your answer, so here is an incomplete example of what I'm trying to do:
class A: public QObject { public: //constructor an destructor void methoda(int a); int geta() const; //return m_a B *m_B;//see below private: int m_a; } class B: public QObject { public: //constructor an destructor void methodb(int b); int getb() const; //return m_b A *m_A; private: int m_b; } int main(); { //everything is initialized B *BB= new *B(); A *AA= new *A(); //somehow set BB->m_A=AA and AA->m_B=BB QThread thread(BB); thread.start(); //two action that read the other class AA->methoda(AA->m_B->getb()); BB->methodb(BB->m_A->geta()); //do stuff...
At no moment something is modified. Does that need mutex or not?
-
@Kent-Dorfman I'm not really sure to understand your answer, so here is an incomplete example of what I'm trying to do:
class A: public QObject { public: //constructor an destructor void methoda(int a); int geta() const; //return m_a B *m_B;//see below private: int m_a; } class B: public QObject { public: //constructor an destructor void methodb(int b); int getb() const; //return m_b A *m_A; private: int m_b; } int main(); { //everything is initialized B *BB= new *B(); A *AA= new *A(); //somehow set BB->m_A=AA and AA->m_B=BB QThread thread(BB); thread.start(); //two action that read the other class AA->methoda(AA->m_B->getb()); BB->methodb(BB->m_A->geta()); //do stuff...
At no moment something is modified. Does that need mutex or not?
If you don't have experience with low-level threading primitives, then I kindly suggest you stick to signal-slot connections. The former can lead to difficult to diagnose errors that may not be trivial to fix. At least with the signal-slot mechanism you get serialization out of the box, which by the way is suitable for most practical cases.
-
If you don't have experience with low-level threading primitives, then I kindly suggest you stick to signal-slot connections. The former can lead to difficult to diagnose errors that may not be trivial to fix. At least with the signal-slot mechanism you get serialization out of the box, which by the way is suitable for most practical cases.
@kshegunov Please, don't think that it is the first time that I encounter something that I'm not familiar with. If I would have stick to what I know in order to accomplish something, I wouldn't accomplished anything. If you are trying to tell me that what I'm asking can't be answered here because its too complicated for a simple post and you might need to wrote a book in order to do so, then tell it to me.
-
@kshegunov Please, don't think that it is the first time that I encounter something that I'm not familiar with. If I would have stick to what I know in order to accomplish something, I wouldn't accomplished anything. If you are trying to tell me that what I'm asking can't be answered here because its too complicated for a simple post and you might need to wrote a book in order to do so, then tell it to me.
@Factao I think what @kshegunov tried to tell you is that in most cases signals/slots are enough and the right way in Qt to communicate between threads. Low level multi-threading is indeed a complex topic, but nobody here forbids you to learn it. But it is not really possible to explain it in a post in a forum. You should look for tutorials/books.
Regarding locking for read access see https://doc.qt.io/qt-5/qreadwritelock.html -
@kshegunov Please, don't think that it is the first time that I encounter something that I'm not familiar with. If I would have stick to what I know in order to accomplish something, I wouldn't accomplished anything. If you are trying to tell me that what I'm asking can't be answered here because its too complicated for a simple post and you might need to wrote a book in order to do so, then tell it to me.
@Factao
Hi @Factao,
well, as always I hope I’m being understood correctly due to my English ;)
I joined at forum about a year ago and I’ve been active only for some months, I think nobody knows somebody, at least, is true for most of us, so it is not easy knowing coding level of someone only by his/her post.
I have always found someone helps me, directly to me or indirectly about post of somebody else.
Sometimes the answers can seem obvious, only because who wrote don’t know your or my level of coding or Qt.
Please don't take it personally, at least I do this.Having said that, let’s come back about synchronization of thread, if you don’t want to use signals and slots you must use some mechanisms to avoid a simultaneous access to a member of thread, normally I use QMutex, so what I say it is certainly true for QMutex, but I think it is same for the other mechanisms.
In both thead you must declare a Qmutex and you must call lock and unlock before access a member of class.
In your H:
QMutex myMutex.In your cpp
void myClass::setMyIntValue(int newValue)
{
myMutex,lock();
mMyMemberInt = newValue;
myMutex,unlock();
}Please pay attention, if 2 or more threads call setMyIntValue only the first will be executed, the others will waiting for unlock to be executed.
In Short lock of mutex blocks execution of next caller until unlock.Regards
CP71 -
@kshegunov Please, don't think that it is the first time that I encounter something that I'm not familiar with. If I would have stick to what I know in order to accomplish something, I wouldn't accomplished anything. If you are trying to tell me that what I'm asking can't be answered here because its too complicated for a simple post and you might need to wrote a book in order to do so, then tell it to me.
@jsulm said in Question about QThread and how thread work in general.:
I think what @kshegunov tried to tell you is that in most cases signals/slots are enough and the right way in Qt to communicate between threads
That's exactly right. This is what I meant. There's nothing wrong with low-level threading, but most of the time with Qt it's not necessary.
-
@jsulm said in Question about QThread and how thread work in general.:
I think what @kshegunov tried to tell you is that in most cases signals/slots are enough and the right way in Qt to communicate between threads
That's exactly right. This is what I meant. There's nothing wrong with low-level threading, but most of the time with Qt it's not necessary.
@kshegunov Then I didn't understand the meaning of your first intervention. I apoligize
@kshegunov and @jsulm . I'm using slots and signals in order to command the worker thread, but this last one, when not doing a specific task, is within a loop, constantly reading value from a servo and saving them. Since there is a lot of variable that change frequently, emitting a signal for every one of them might slow the application down, due to how signal/slot work.
@CP71 Thanks, this is the example that I was looking for. To summarize, I'm locking when a thread is using a function that use a specific value and nothing more. So making a specific and short function that only return or modify the value is a good way to avoid traffic while multiple thread are accessing the same thing.
edit: After trying it, now I see that there is an issue with the function other than void, I can't do:int m_something;// private element of class int class::returnSomething() const { mutex.lock() return m_something; mutex.unlock() };
If I'm doing that:
int class::returnSomething() const { mutex.lock(); int something(m_something); mutex.unlock(); return something; }
Is this what we are trying to do here? From what I understand, our goal Is to prevent two thread to access the same data simultaneously, not the same function.
So, to be sure of getting it, here is a summarize of what I get out of this topic:
We need to lock data when a thread is accessing it to be sure that the data going to stay where it should be during the operation. If we don't do it, a thread from another core could possibly "steal" the data that we need and create a little problems in our program.Is this approximately true? Or do I miss something?
-
@Factao said in Question about QThread and how thread work in general.:
We need to lock data when a thread is accessing it to be sure that the data going to stay where it should be during the operation. If we don't do it, a thread from another core could possibly "steal" the data that we need and create a little problems in our program.
Steal the data isn't the correct terminology, but you are essentially correct. You shouldn't care about multiple siumulatneous reads. It's only when something is changing the data that locking becomes a concern.
And for what it's worth, your application is beginning to smell very much like something that is not really appropriate for high level Qt on a PC or real CPU. real-time functions should usually be delegated to micro-controllers running RTOS programs specifically designed to handle real-time IO and then send agregate info to a higher level computer program on a real CPU.
Of course you don't elaborate on whether this is a hobbyist level, academic/learning, or for work, project.