[SOLVED]Cann't get correct mutex status
-
Dear Forumers, I cann't synchronise threads (main and parallel one ) using mutex. When I emit signal from parallel thread to main and use mutex in main, the parallel thread are still working. I wrote a little example (see below). Where is my mistake ? It looks like I didn't understand something. Thank you all in advance for your time.
main.cpp
@
#include <myWindow.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow *my_window = new MainWindow();my_window -> show();
return app.exec();
}
@myWindow.h
@
#include <QMutex>class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
QMutex *mutex_MainWindow;
MainWindow( QWidget *parent = 0);private slots:
void DoMessageReceived();
};#endif // MYWINDOW_H
@myWindow.cpp
@
#include "myWindow.h"
#include "mythread.h"
#include <QtTest/QTest>//В .pro файле добавить надо QT += testlibMainWindow::MainWindow( QWidget *parent) :
QMainWindow(parent),
mutex_MainWindow(new QMutex)
{
MyThread *mThread= new MyThread(mutex_MainWindow);connect(
mThread, SIGNAL( MessageReceived () ),
this, SLOT ( DoMessageReceived () )
);
mThread -> start();
}
void MainWindow::DoMessageReceived(){
if( mutex_MainWindow -> tryLock ()) {
qDebug() << "MainWindow::DoMessageReceivedMessage: tryLocked == true"
<< "\n------------------------------------------------------------";
mutex_MainWindow -> unlock();
QMutexLocker locker (mutex_MainWindow);
}
else
qDebug() << "myWidget::receivedCanMessage: tryLocked == false"
<< "\n------------------------------------------------------------";
qDebug() << "-----------------------------------------mutex_MainWindow = "
<< mutex_MainWindow;
qDebug()
<< "***** MainWindow::DoMessageReceived: mutex locked -> QTest::qSleep(300000000 ms) ";
QTest::qSleep(300000000);
qDebug()
<< "****** MainWindow::DoMessageReceived: continue after qSleep(300000000 ms) ";
return;
}
@mythread.h
@
#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QApplication>
#include <QtGui>
#include <QtCore>
#include <QMutex>
#include <QMutexLocker>
#include <QDebug>class MyThread : public QThread
{
Q_OBJECTprivate:
QMutex *mutex_thread;
public:
explicit MyThread( QMutex * , QWidget *parent = 0 );
bool running;
int n_cycle;
protected:
void run();signals :
void MessageReceived();
};#endif // MYTHREAD_H
@mythread.cpp
@
#include "mythread.h"MyThread::MyThread(QMutex* mu, QWidget *parent ) :
QThread( parent ),
mutex_thread(mu),
running(true),
n_cycle(0)
{
qDebug() << "Constructor : mutex ="
<< mutex_thread;
}void MyThread::run(){
while (running) {
qDebug() << " thread running -------------------------mutex ="
<< mutex_thread;
// QMutexLocker locker (mutex_ObjectGetting);
if( mutex_thread -> tryLock ()) {
qDebug()
<< "thread: tryLocked==true"<< "\n------------------------------------------------------------";
mutex_thread -> unlock ();
}
else
qDebug()
<< "thread: tryLocked==false"
<< "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
mutex_thread -> lock ();
// doing something ...
mutex_thread -> unlock ();
emit MessageReceived();
qDebug()
<< "thread: emit MessageReceived(), mutex unlocked -> usleep(10000) ";
usleep(10000);
n_cycle++;
if(n_cycle == 4) running = false;
}
}
@ -
Hi,
What are you trying to do exactly ? Currently you are just locking your mutex in their respective thread and your code doesn't look like it needs mutex at all
-
How about sharing some output. Also did you try set the Recursive attribute for the QMutex.
Also in your thread you always do an unlock, even if not locked here. According to the QMutex documentation for unlock():
bq. Unlocks the mutex. Attempting to unlock a mutex in a different thread to the one that locked it results in an error. Unlocking a mutex that is not locked results in undefined behavior.
-
Hi, SGaist, I need to get a message in the parallel thread and send one to the main thread to treat one and want to stop the parallel thread till the main thread will finish the treatment of the current message. I can do it by the QQueue and so on but I decided that a mutex is appropriate way to do this. And I knew about the Recursive attribute for the QMutex but I thought that I dont't need one but maybe I was wrong ?
For DBoosalis: this is an example to demonstrate the problem. It looks like the mutex doesn't work like I want. In real soft I got this problem and cann't overcome one myself. I am using tryLock() to see the mutex is locked or is not. If I didn't mistake I always locked and unlock mutex in the same thread. That's it.
Thank you for your time. Any suggestion ? -
Dear Forumers, I see that I did something wrong in my example. In the parallel thread I am using tryLock and forgot that it will continue even the mutex was locked. So I corrected it. Now it works like I intended to show the problem. The parallel thread has not to work after the emiting signal receivedMessage till the main thread will finish to process received message but it works. Thank you.
-
Then it should rather be a QWaitCondition or use a signal connected using the Qt::BlockingQueuedConnection type.
-
Dear SGaist, indeed I have used Qt::BlockingQueuedConnection and it works properly. thank you very much. So the p[roblem solved also I doesn't understand why the mutex doesn't work the same way. Anyway the solution looks even better because your valuable advice. Here is the changed codes just in case for reference:
myWindow.cpp
@
#include "myWindow.h"
#include "mythread.h"
#include <QtTest/QTest>//В .pro файле добавить надо QT += testlibMainWindow::MainWindow( QWidget *parent) :
QMainWindow(parent),
mutex_MainWindow(new QMutex)
{
MyThread *mThread= new MyThread(mutex_MainWindow);connect(
mThread, SIGNAL( MessageReceived () ),
this, SLOT ( DoMessageReceived () ),
Qt::BlockingQueuedConnection);
mThread -> start();
}
void MainWindow::DoMessageReceived(){
qDebug()
<< "***** MainWindow::DoMessageReceived -> Qt::BlockingQueuedConnection\n"
<< "***** called QTest::qSleep(3000) ";
QTest::qSleep(3000);
qDebug()
<< "****** MainWindow::DoMessageReceived: continue after qSleep(3000 ms) ";
return;
}
@mythread.cpp
@
#include "mythread.h"MyThread::MyThread(QMutex* mu, QWidget *parent ) :
QThread( parent ),
mutex_thread(mu),
running(true),
n_cycle(0)
{
qDebug() << "Constructor : mutex ="
<< mutex_thread;
}void MyThread::run(){
while (running) {
n_cycle++;
qDebug() << " thread running: emit MessageReceived n_cycle = " << n_cycle;emit MessageReceived(); if(n_cycle == 4) running = false;
}
}
@ -
A mutex is not meant to be used as a "waiting point". It's used to protect access to a resource that can be accessed from several threads.
-
That's what I have been intended to do. I get message in the parallel thread and send one to the main thread and flash the mutex to avoid the access to reading a new message. But it doesn't work in my case. In my soft I have several threads but I intended to protect resourses
(the structure where I put the read message) only from one of them as in my simple example. The Qt::BlockingQueuedConnection does the same thing for me but I thought that mutex has to do the same, isn't it ? -
Not necessarily no. You should also take a look QSemaphore, QWaitCondition and QReadWriteLock