tags:

views:

192

answers:

3

I am just learning Qt and have a very basic question.

If there is a (function scope) variable in a slot, and the slot is called multiple times, each time before the last call has returned (is this even possible?), will the variable be overwritten each time? In the sense that, if the slot is called before the previous run has returned, wouldn't that cause errors?

Thanks.

+2  A: 

Yes if the calls are made from different threads AND you are using direct connection.

If you use queued connections then the slot calls will be performed one after another on event loop which is ran on the thread your receiving object belongs to. (edit thanks to Idan K comment).

Checkout Signal and slots's queued connection or QMutexLocker to solve your problem.

poulejapon
I believe queued connections are run on the event loop that the QObject is attached to. So for example if you create a QObject inside QThread::run(), it's slot will be processed in the context of the QThread.
Idan K
This is right! Thank you!
poulejapon
I disagree, but there might not be enough information to say for sure. If it is a *function-scope* variable, nothing should be overwriting it, even in different threads running concurrently. In that case, it should work fine. However, if it is a function-scope reference or pointer variable, the source data may have changed, which could cause problems.
Caleb Huitt - cjhuitt
Didn't read the function scope part.
poulejapon
+1  A: 

If you truly use function scope variables, then it shouldn't matter. Example:

class WheelSpinner : public QThread
{
Q_OBJECT;
public:
    WheelSpinner( QObject* receiver, const char* slot )
    {
        connect( this, SIGNAL( valueChanged( int ) ), receiver, slot,
                 Qt::DirectConnect );
    }

    void run()
    {
        for ( int i = 0; i < 100000; ++i )
        {
            emit ( valueChanged( i ) );
        }
    }

public signals:
    void valueChanged( int value );
};

class ProgressTracker : public QObject
{
Q_OBJECT;
public:
    ProgressTracker() { }

public slots:
    void updateProgress( int value )
    {
        // While in this function, "value" will always be the proper 
        // value corresponding to the signal that was emitted.
        if ( value == 100000 )
        {
            // This will cause us to quit when the *first thread* that 
            // emits valueChanged with the value of 100000 gets to this point.
            // Of course, other threads may get to this point also before the 
            // program manages to quit.
            QApplication::quit();
        }
    }
};

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    ProgressTracker tracker;
    WheelSpinner spinner1( &tracker, SLOT( updateProgress( int  ) ) );
    WheelSpinner spinner2( &tracker, SLOT( updateProgress( int  ) ) );
    WheelSpinner spinner3( &tracker, SLOT( updateProgress( int  ) ) );

    spinner1.run();
    spinner2.run();
    spinner3.run();

    return ( app.exec() );
}
Caleb Huitt - cjhuitt
So in this case, you are saying that if the same WheelSpinner object (say spinner2) calls updateProgress for i, and the i-1th call hasn't completed yet, it still will run fine?
trex279
@trex279: First of all, with a direct connection, if spinner2 calls updateProgress for i, it won't continue until the updateProgress function is complete. That portion is sequential. If, however, spinner1 runs for i + 1 while spinner2 is still running the same function for i, both will execute properly.
Caleb Huitt - cjhuitt
+1  A: 

As long as the function is reentrant there is no problem.

TimW
An important note is that QObject::sender() is _not_ reentrant.
Marcus Lindblom