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

Qt-interest Archive, August 2007
Thread misunderstanding


Message 1 in thread

Hi all,

I am trying to use QThread and QSemaphore for the first time and it seems
that I don't understand very well this stuff.

My Thread is derived of a QThread but has a pointer to a semaphore m_Sem.
The run function is reimplemented and looks like this :
{
 m_Sem->acquire();

[do my stuff]

 m_Sem->release();
}

The calling function looks like that
{
 QSemaphore sem( threadNum );
    for ( int i=0;i< m_WidgetList.size();i++ ) {
       myThread th(  &sem,... );
        th.start();
    }
    QProgressBar b( this );
    b.setMaximum( 0 );
    b.setMinimum( 0 );
    b.show();
    while ( ! sem.tryAcquire( threadNum  ) )
    {
        QApplication::processEvents();
    }
}

When I run this code, I got a segfautl and the message that a least one
running thread has been destroyed though my idea was that the loop at the
end of the function would wait for every thread to be finished before
exiting.
What I am doing wrong here ?

TIA

Alain

--
 [ signature omitted ] 

Message 2 in thread

in my program i used:

QApplication::processEvents(QEventLoop::WaitForMoreEvents)

cheers seb

On Tuesday 07 August 2007 20:28:22 denebet wrote:
> Hi all,
>
> I am trying to use QThread and QSemaphore for the first time and it seems
> that I don't understand very well this stuff.
>
> My Thread is derived of a QThread but has a pointer to a semaphore m_Sem.
> The run function is reimplemented and looks like this :
> {
>  m_Sem->acquire();
>
> [do my stuff]
>
>  m_Sem->release();
> }
>
> The calling function looks like that
> {
>  QSemaphore sem( threadNum );
>     for ( int i=0;i< m_WidgetList.size();i++ ) {
>        myThread th(  &sem,... );
>         th.start();
>     }
>     QProgressBar b( this );
>     b.setMaximum( 0 );
>     b.setMinimum( 0 );
>     b.show();
>     while ( ! sem.tryAcquire( threadNum  ) )
>     {
>         QApplication::processEvents();
>     }
> }
>
> When I run this code, I got a segfautl and the message that a least one
> running thread has been destroyed though my idea was that the loop at the
> end of the function would wait for every thread to be finished before
> exiting.
> What I am doing wrong here ?
>
> TIA
>
> Alain
>
> --
> 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 3 in thread

On Tuesday 07 August 2007, denebet wrote:
> Hi all,
>
> I am trying to use QThread and QSemaphore for the first time and it seems
> that I don't understand very well this stuff.
>

Ok. I'll give it a shot.....

> My Thread is derived of a QThread but has a pointer to a semaphore m_Sem.
> The run function is reimplemented and looks like this :
> {
>  m_Sem->acquire();

Doh! Do *NOT* use semaphores if you need to protect data in the same process. 
Use Mutexes instead. A Mutex "lives" in userspace and is meant for this 
purpose. A Semaphore is used the same but protects data across *processes* In 
this case, the semaphore exists at kernel level, making it very expensive to 
set and release. For this purpose, a call to kernel level has to be made.

>
> [do my stuff]
>
>  m_Sem->release();
> }
>
> The calling function looks like that
> {
>  QSemaphore sem( threadNum );
>     for ( int i=0;i< m_WidgetList.size();i++ ) {
>        myThread th(  &sem,... );
>         th.start();
>     }
>     QProgressBar b( this );
>     b.setMaximum( 0 );
>     b.setMinimum( 0 );
>     b.show();
>     while ( ! sem.tryAcquire( threadNum  ) )
>     {
>         QApplication::processEvents();
>     }
> }
>
> When I run this code, I got a segfautl and the message that a least one
> running thread has been destroyed though my idea was that the loop at the
> end of the function would wait for every thread to be finished before
> exiting.
> What I am doing wrong here ?

Wow! Ehm... This is not easily said. In a multi-threaded app, the heap is used 
as shared memory between threads. Every object created there (the 
new-operator does that) is accessible by pointer-passing. Inside such an 
object, a method can exist, protected by a Mutex. 

Or in (pseudo)code..

----------[ Begin ]------------------

----------[ Shared Object ]----------

class sharedObject
{
    public:
        sharedObject();
        ~sharedObject();

        void callMethod();

    private:
	QMutex	*pMutex;
};

sharedObject::sharedObject()
{
    pMutex = new QMutex();
}

sharedObject::~sharedObject()
{
}

void sharedObject::callMethod
{
    if( pMutex->tryLock() )
    {
        // Do your stuff

        pMutex->unLock();
    }
}

----------[ Threaded Object ]----------

class MyThread : public QThread
{
    Q_OBJECT
    public:
        MyThread( sharedObject *pObject );
        void run();

    private:
        sharedObject *m_pSharedObject;
};

MyThread::MyThread( sharedObject *pObject ) 
 : m_pSharedObject( pObject )
{
    // Initialisation here
}

void MyThread::run()
{
    if( m_pSharedObject )
    {
        m_pSharedObject->callMethod();
    }
    exec();	<<-- Very important if you use signals / slots 
}

----------[ Main ]----------

int main( int argc, char *argv[] )
{
    QCoreApplication coreApp( argc, argv );
    sharedObject *pSharedObject = new sharedObject();

    myThread *pMyThread = new MyThread( pSharedObject );
    pMyThread->start();

    coreApp.exec();
}

----------[ End ]------------------

I'm sure there are a million ways to do this, but this has been proven working 
in many projects I did. 

Hope this helps..

>
> TIA
>
> Alain
>
> --
> 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 4 in thread

Peter M. Groen wrote:

> 
> Wow! Ehm... This is not easily said. In a multi-threaded app, the heap is
> used as shared memory between threads. Every object created there (the
> new-operator does that) is accessible by pointer-passing. Inside such an
> object, a method can exist, protected by a Mutex.
> 
> Or in (pseudo)code..
> 
> ----------[ Begin ]------------------
> 
> ----------[ Shared Object ]----------
> 
> class sharedObject
> {
>     public:
>         sharedObject();
>         ~sharedObject();
> 
>         void callMethod();
> 
>     private:
> QMutex        *pMutex;
> };
> 
> sharedObject::sharedObject()
> {
>     pMutex = new QMutex();
> }
> 
> sharedObject::~sharedObject()
> {
> }
> 
> void sharedObject::callMethod
> {
>     if( pMutex->tryLock() )
>     {
>         // Do your stuff
> 
>         pMutex->unLock();
>     }
> }
> 
> ----------[ Threaded Object ]----------
> 
> class MyThread : public QThread
> {
>     Q_OBJECT
>     public:
>         MyThread( sharedObject *pObject );
>         void run();
> 
>     private:
>         sharedObject *m_pSharedObject;
> };
> 
> MyThread::MyThread( sharedObject *pObject )
>  : m_pSharedObject( pObject )
> {
>     // Initialisation here
> }
> 
> void MyThread::run()
> {
>     if( m_pSharedObject )
>     {
>         m_pSharedObject->callMethod();
>     }
>     exec();   <<-- Very important if you use signals / slots
> }
> 
> ----------[ Main ]----------
> 
> int main( int argc, char *argv[] )
> {
>     QCoreApplication coreApp( argc, argv );
>     sharedObject *pSharedObject = new sharedObject();
> 
>     myThread *pMyThread = new MyThread( pSharedObject );
>     pMyThread->start();
> 
>     coreApp.exec();
> }
> 
> ----------[ End ]------------------
> 
> I'm sure there are a million ways to do this, but this has been proven
> working in many projects I did.
> 
> Hope this helps..
> 

Thanks for your detailed answer.  Please forgive me if I am stupid but I
understand that your code is made so that whatever the number of  MyThread
objects created there will be only one callMethod running at the same time.
Is this right ?

My goal is a little bit different : I want to allow a fixed number of
threads running at the same time (they work on different files) and wait
that every thread is finished before the function where they are created
exits (in fact, each thread resizes a picture, I want to display a progress
bar during this time and when every thread is finished, hide the progress
bar and make my soft go on).

Regards,

Alain

--
 [ signature omitted ] 

Message 5 in thread

On Wednesday 08 August 2007, denebet wrote:

------------[ Begin ]---------------------

> Thanks for your detailed answer.  Please forgive me if I am stupid but I
> understand that your code is made so that whatever the number of  MyThread
> objects created there will be only one callMethod running at the same time.
> Is this right ?

Not knowing something comes from lack of knowledge, not stupidity. Stupidity 
is *thinking* you know everything and not trying to learn something.....

In my example I only tried to explain *where* the mutex lives, not to make a 
method run single or locked (*That* would kill the threading idea, wouldn't 
it?).. Normally you lock a mutex the moment you start changing private 
members of the class and releasing them immediately afterwards to avoid race 
conditions. ( See the "Dining Philosophers Problem" ).
I only created one thread, but you can imagine it is possible to use multiple.

When a thread tries to lock a mutex that is locked from another thread, it 
will sleep. Everytime the scheduler is activating this thread, it tries 
locking the mutex until it succeeds.. (When it tries to lock a mutex that was 
lock by itself, it causes a "deadlock". This happens when you forget to 
unlock the mutex when you're done. Luckily, Qt-checks for that when compiled 
in Debug mode and asserts..)

Or in our callMethod()

{
    // Do a *lot* of heavy work....
    pMutex->lock(); <<== If locking fails, it waits until it can...
    m_pPrivMem = <Some value>;
    pMutex->unlock();
}

>
> My goal is a little bit different : I want to allow a fixed number of
> threads running at the same time (they work on different files) and wait
> that every thread is finished before the function where they are created
> exits (in fact, each thread resizes a picture, I want to display a progress
> bar during this time and when every thread is finished, hide the progress
> bar and make my soft go on).
>

Ehm.. Ok. I hope you are not updating the GUI from the thread, because that is 
not (yet) possible... (It would explain your segfaults..) By using a shared 
object in the main thread, it can update the GUI (Which also exists in the 
main thread). Try reading something about signals and slots between threads 
in the Qt-Assistant. It's actually quite good.

Letting the "Soft go on" could be done by an object creating all the threads, 
catching their signals if they are finished doing their stuff, removing the 
thread-objects and signalling the application that it is finished.. 

For now: ... Have fun! :)

-- 
 [ signature omitted ] 

Message 6 in thread

Peter M. Groen wrote:
> 
> Ehm.. Ok. I hope you are not updating the GUI from the thread, because
> that is not (yet) possible... (It would explain your segfaults..) By using
> a shared object in the main thread, it can update the GUI (Which also
> exists in the main thread). Try reading something about signals and slots
> between threads in the Qt-Assistant. It's actually quite good.
> 
> Letting the "Soft go on" could be done by an object creating all the
> threads, catching their signals if they are finished doing their stuff,
> removing the thread-objects and signalling the application that it is
> finished..

Ok, thanks for you explanations.

Alain

--
 [ signature omitted ]