Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

Qt-interest Archive, January 2008
how to suspend/resume a thread?


Message 1 in thread

I hope a thread can be suspended (resumed) by click a suspend (resume) 
button.

Here is a connection:
    connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread, 
SLOT(suspend()));

Here is the slot:
void MyThread::suspend()
{
    susp_mutex.lock();
    susp_flag=true;
    susp_mutex.unlock();
}

, and here is the wait condition in the thread loop:
    {
        while(MyThread::susp_flag)
            MyThread::susp_cond.wait(&MyThread::susp_mutex);
    }

I hope the thread can be suspended, but instead, I get error:
"A mutex must be unlocked in the same thread that locked it"

What's wrong? Could you mind sharing with me your experience on 
suspend/resume a thread?

Thanks in advance,
Lingfa


--
 [ signature omitted ] 

Message 2 in thread

Lingfa Yang wrote:
> I hope a thread can be suspended (resumed) by click a suspend (resume) 
> button.
>
> Here is a connection:
>    connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread, 
> SLOT(suspend()));


Try adding Qt::QueuedConnection as the 5th argument to connect(). That 
way, the suspend() function will execute in the thread, instead of in 
the GUI thread.

--Dave

--
 [ signature omitted ] 

Message 3 in thread

> Try adding Qt::QueuedConnection as the 5th argument to connect(). That 
> way, the suspend() function will execute in the thread, instead of in 
> the GUI thread.

Thank you for your reply. I did it, but I got the same error.
Lingfa

--
 [ signature omitted ] 

Message 4 in thread

Lingfa Yang wrote:

> , and here is the wait condition in the thread loop:
>    {
>        while(MyThread::susp_flag)
>            MyThread::susp_cond.wait(&MyThread::susp_mutex);
>    }
> 
> I hope the thread can be suspended, but instead, I get error:
> "A mutex must be unlocked in the same thread that locked it"

I suspect from the code that you are running the while
loop in a thread that is not MyThread and it is that
thread in which the condition variable unlocks the mutex,
which would lead to the message that you see.

Usually a thread will own its mutexes and cond. vars,
(ie. they will be private variables in a thread class)
and they should not be made available to other threads.

-- 
 [ signature omitted ] 

Message 5 in thread

Stephen Collyer wrote:
> Lingfa Yang wrote:
>
>   
>> , and here is the wait condition in the thread loop:
>>    {
>>        while(MyThread::susp_flag)
>>            MyThread::susp_cond.wait(&MyThread::susp_mutex);
>>    }
>>
>> I hope the thread can be suspended, but instead, I get error:
>> "A mutex must be unlocked in the same thread that locked it"
>>     
>
> I suspect from the code that you are running the while
> loop in a thread that is not MyThread and it is that
> thread in which the condition variable unlocks the mutex,
> which would lead to the message that you see.
>
> Usually a thread will own its mutexes and cond. vars,
> (ie. they will be private variables in a thread class)
> and they should not be made available to other threads.
>   
Stephen,

Thank you for your reply. I think you are right. I made changes to make 
sure the mutex and condition are created in the same thread:
{
        while(this->susp_flag)
            this->pCondition->wait(this->pMutex);
}

Still, I got the same error.

More idea?
Lingfa

--
 [ signature omitted ] 

Message 6 in thread

Lingfa Yang wrote:
> Stephen Collyer wrote:

>> Usually a thread will own its mutexes and cond. vars,
>> (ie. they will be private variables in a thread class)
>> and they should not be made available to other threads.

Ignore this. It's nonsense as stated.

> Thank you for your reply. I think you are right. I made changes to make
> sure the mutex and condition are created in the same thread:
> {
>        while(this->susp_flag)
>            this->pCondition->wait(this->pMutex);
> }
> 
> Still, I got the same error.

Can you put up more of the code ? It's not at
all clear how the whole thing fits together -
show the thread creation, and the classes you've
written and it'll be clearer as to what's going on.

-- 
 [ signature omitted ] 

Message 7 in thread

> Can you put up more of the code ? It's not at
> all clear how the whole thing fits together -
> show the thread creation, and the classes you've
> written and it'll be clearer as to what's going on.
>   
Thank you. Here come the whole impl.
1) "MyThread.h"

#include <QThread>
class PackageCore;

class MyThread : public QThread  
{
    Q_OBJECT
public slots:
    void suspend();
    void resume();
public:
    MyThread(PackageCore *core);
    virtual ~MyThread();
 
    void run();
protected:
    PackageCore *core;
};

2) "MyThread.cpp"
#include "MyThread.h"
#include "PackageCore.h"
#include <QMutex>
#include <QWaitCondition>

MyThread::MyThread(PackageCore *core)
: core(core)
{}
MyThread::~MyThread(){}

void MyThread::run()
{
    core->setStop(false);
    core->threadRun(); // heavy duty, time-costed, return back in 
minutes or hours or days...
}

void MyThread::suspend()
{
    core->pMutex->lock();
    core->susp_flag=true;
    core->pMutex->unlock();
}

void MyThread::resume()
{
    core->pMutex->lock();
    core->susp_flag=false;
    core->pMutex->unlock();
    core->pCondition->wakeOne();
}

3) The core:
void PackageCore::threadRun()
{
    pMutex = new QMutex;
    pCondition = new QWaitCondition;
    switch(m_threadFunc)
    {
    case 0: // Plain text
        extractPlainText();
        break;
    case 1: // tagged XML
        extractXml();
        break;
    case 2: // unzipAll
        ok = unzipAll();
        break;
    //...
    }
    delete pMutex; pMutex = NULL;
    delete pCondition; pCondition = NULL;
}

4) The loop in subclass:
void OoXmlCore::extractText(const QString &partName, QTextStream &os)
{
    emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
    // ...
    emit setRange(0, N);
    for(int i=0; i<N; ++i)
    {
        if(m_stop) break;
        emit progressValue(i); // To drive progress bar
        while(this->susp_flag)
            this->pCondition->wait(this->pMutex);
       //...
    }
}

--
 [ signature omitted ] 

Message 8 in thread

Lingfa,

if you whant just suspend one thread and don't need to synchronize many 
of them code like below should be enough:

class RunningThread{

static QMutex suspend_mutex;

   run(){
     while(){
       suspend_mutex.lock(); suspend_mutex.unlock();
      }
    }

    suspend(){
      suspend_mutex.trylock();
    }

}





Lingfa Yang wrote:
> 
>> Can you put up more of the code ? It's not at
>> all clear how the whole thing fits together -
>> show the thread creation, and the classes you've
>> written and it'll be clearer as to what's going on.
>>   
> Thank you. Here come the whole impl.
> 1) "MyThread.h"
> 
> #include <QThread>
> class PackageCore;
> 
> class MyThread : public QThread  {
>    Q_OBJECT
> public slots:
>    void suspend();
>    void resume();
> public:
>    MyThread(PackageCore *core);
>    virtual ~MyThread();
> 
>    void run();
> protected:
>    PackageCore *core;
> };
> 
> 2) "MyThread.cpp"
> #include "MyThread.h"
> #include "PackageCore.h"
> #include <QMutex>
> #include <QWaitCondition>
> 
> MyThread::MyThread(PackageCore *core)
> : core(core)
> {}
> MyThread::~MyThread(){}
> 
> void MyThread::run()
> {
>    core->setStop(false);
>    core->threadRun(); // heavy duty, time-costed, return back in minutes 
> or hours or days...
> }
> 
> void MyThread::suspend()
> {
>    core->pMutex->lock();
>    core->susp_flag=true;
>    core->pMutex->unlock();
> }
> 
> void MyThread::resume()
> {
>    core->pMutex->lock();
>    core->susp_flag=false;
>    core->pMutex->unlock();
>    core->pCondition->wakeOne();
> }
> 
> 3) The core:
> void PackageCore::threadRun()
> {
>    pMutex = new QMutex;
>    pCondition = new QWaitCondition;
>    switch(m_threadFunc)
>    {
>    case 0: // Plain text
>        extractPlainText();
>        break;
>    case 1: // tagged XML
>        extractXml();
>        break;
>    case 2: // unzipAll
>        ok = unzipAll();
>        break;
>    //...
>    }
>    delete pMutex; pMutex = NULL;
>    delete pCondition; pCondition = NULL;
> }
> 
> 4) The loop in subclass:
> void OoXmlCore::extractText(const QString &partName, QTextStream &os)
> {
>    emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
>    // ...
>    emit setRange(0, N);
>    for(int i=0; i<N; ++i)
>    {
>        if(m_stop) break;
>        emit progressValue(i); // To drive progress bar
>        while(this->susp_flag)
>            this->pCondition->wait(this->pMutex);
>       //...
>    }
> }
> 
> -- 
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with 
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
> 


-- 
 [ signature omitted ] 

Message 9 in thread

and what about QWaitCondition ? 

-----Message d'origine-----
De : Dmitry.Samersoff@xxxxxxx [mailto:Dmitry.Samersoff@xxxxxxx]De la
part de Dmitry Samersoff
Envoyà : mardi 29 janvier 2008 17:48
à : Lingfa Yang
Cc : qt-interest@xxxxxxxxxxxxx
Objet : Re: how to suspend/resume a thread?


Lingfa,

if you whant just suspend one thread and don't need to synchronize many 
of them code like below should be enough:

class RunningThread{

static QMutex suspend_mutex;

   run(){
     while(){
       suspend_mutex.lock(); suspend_mutex.unlock();
      }
    }

    suspend(){
      suspend_mutex.trylock();
    }

}





Lingfa Yang wrote:
> 
>> Can you put up more of the code ? It's not at
>> all clear how the whole thing fits together -
>> show the thread creation, and the classes you've
>> written and it'll be clearer as to what's going on.
>>   
> Thank you. Here come the whole impl.
> 1) "MyThread.h"
> 
> #include <QThread>
> class PackageCore;
> 
> class MyThread : public QThread  {
>    Q_OBJECT
> public slots:
>    void suspend();
>    void resume();
> public:
>    MyThread(PackageCore *core);
>    virtual ~MyThread();
> 
>    void run();
> protected:
>    PackageCore *core;
> };
> 
> 2) "MyThread.cpp"
> #include "MyThread.h"
> #include "PackageCore.h"
> #include <QMutex>
> #include <QWaitCondition>
> 
> MyThread::MyThread(PackageCore *core)
> : core(core)
> {}
> MyThread::~MyThread(){}
> 
> void MyThread::run()
> {
>    core->setStop(false);
>    core->threadRun(); // heavy duty, time-costed, return back in minutes 
> or hours or days...
> }
> 
> void MyThread::suspend()
> {
>    core->pMutex->lock();
>    core->susp_flag=true;
>    core->pMutex->unlock();
> }
> 
> void MyThread::resume()
> {
>    core->pMutex->lock();
>    core->susp_flag=false;
>    core->pMutex->unlock();
>    core->pCondition->wakeOne();
> }
> 
> 3) The core:
> void PackageCore::threadRun()
> {
>    pMutex = new QMutex;
>    pCondition = new QWaitCondition;
>    switch(m_threadFunc)
>    {
>    case 0: // Plain text
>        extractPlainText();
>        break;
>    case 1: // tagged XML
>        extractXml();
>        break;
>    case 2: // unzipAll
>        ok = unzipAll();
>        break;
>    //...
>    }
>    delete pMutex; pMutex = NULL;
>    delete pCondition; pCondition = NULL;
> }
> 
> 4) The loop in subclass:
> void OoXmlCore::extractText(const QString &partName, QTextStream &os)
> {
>    emit setProgressLabel(tr("Working on \"%1\"...").arg(partName));
>    // ...
>    emit setRange(0, N);
>    for(int i=0; i<N; ++i)
>    {
>        if(m_stop) break;
>        emit progressValue(i); // To drive progress bar
>        while(this->susp_flag)
>            this->pCondition->wait(this->pMutex);
>       //...
>    }
> }
> 
> -- 
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with 
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
> 


-- 
 [ signature omitted ] 

Message 10 in thread

Dmitry Samersoff wrote:
> Lingfa,
>
> if you whant just suspend one thread and don't need to synchronize 
> many of them code like below should be enough:
>
> class RunningThread{
>
> static QMutex suspend_mutex;
>
>   run(){
>     while(){
>       suspend_mutex.lock(); suspend_mutex.unlock();
>      }
>    }
>
>    suspend(){
>      suspend_mutex.trylock();
>    }
>
> }

Dmitry,

Cool! The simpler the better. I will try.

Thanks,
Lingfa


--
 [ signature omitted ] 

Message 11 in thread

Lingfa Yang wrote:
>>
>> static QMutex suspend_mutex;
> 
> Cool! The simpler the better. I will try.

Good luck!
Please, don't miss *static* keyword above.

Condition variables designed to wakeup couple of threads at once.
If you have to start/stop the only thread - you don't need it.


-- 
 [ signature omitted ] 

Message 12 in thread

Lingfa Yang wrote:
>I hope a thread can be suspended (resumed) by click a suspend (resume)
>button.

A thread is suspended if it's not doing anything. The call to 
QThread::exec() starts an event loop that waits for events and sleeps 
otherwise.

If you want to block event reception, you'll need to go into a function 
that sleeps on a semaphore (acquire) until another thread allows it to 
continue (release).

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 13 in thread

As my understading, wait() is for synchronizing terminations of threads.

I have ever used sleep(timeout)
	while(susp_flag)
	{
		Sleep(TIMEOUT);
	}
This make the thread hand over cpu priority to other thread for TIMEOUT
secs.
Then, it will wake up and recheck susp_flag after TIMEOUT secs.
wait() without timeout value usually made hang up condition for me.

Or.. I recommend to terminate the thread with storing the current
data by clicking a suspend button, and to restart the thread with recall
the stored data by clicking a resume button.


-----Original Message-----
From: Lingfa Yang [mailto:lingfa@xxxxxxxxxxxx] 
Sent: Tuesday, January 29, 2008 10:03 AM
To: Qt Interest
Subject: how to suspend/resume a thread?

I hope a thread can be suspended (resumed) by click a suspend (resume) 
button.

Here is a connection:
    connect(progressCtrl->suspendButton, SIGNAL(clicked()), thread, 
SLOT(suspend()));

Here is the slot:
void MyThread::suspend()
{
    susp_mutex.lock();
    susp_flag=true;
    susp_mutex.unlock();
}

, and here is the wait condition in the thread loop:
    {
        while(MyThread::susp_flag)
            MyThread::susp_cond.wait(&MyThread::susp_mutex);
    }

I hope the thread can be suspended, but instead, I get error:
"A mutex must be unlocked in the same thread that locked it"

What's wrong? Could you mind sharing with me your experience on 
suspend/resume a thread?

Thanks in advance,
Lingfa


--
 [ signature omitted ]