views:

85

answers:

2

Apart from main thread, I've ThinkerThread object _thinker whose finished() signal is connected to main thread's slot:

connect(&_thinker, SIGNAL(finished()), this, SLOT(autoMove()));

The slot autoMove() causes _thinker to initialize and run again:

_thinker.setState(/* set internal variables to run properly */);
_thinker.start();

This way _thinker can continue to run with new data and give some feedback to user in the main thread with autoMove() slot.

The problem is when user wishes to load a new state for _thinker (may be from file or some other menu action), I cannot synchronous two states of _thinker.

Suppose that _thinker is running, and user loads a new state from a file. Now, when _thinker finished(), it will call autoMove() and show feedback. But it is possible that wrong feedback is given to the user, because, may be loading from file causes internal state to be changed. That means, _thinker's internal state and main thread's internal states are not same.

  1. _thinker starts, with states say, s0.
  2. User loads another state from file, say s1.
  3. _thinker finished and autoMove() executes.

So after step 3, autoMove() will give feedback for state s0, which is not expected. What I want to do is to stop execution of _thinker when user loads new state from file. I think my design is poor and I want to know the best practice in this case. My load function initializes _thinker in the same way autoMove() does, calling the same function (there is another function that calles _thinker.setState() and start()).

Right now I've done the following in load() function:

disconnect(&_thinker, SIGNAL(finished()), this, SLOT(autoMove()));
_thinker.terminate();
_thinker.wait();
connect(&_thinker, SIGNAL(finished()), this, SLOT(autoMove()));

This does not eliminate the problem completely, that is, autoMove() is still called and gives previous state's feedback. I'm using Qt Creator 1.2.1 with Qt version 4.5.2 in Windows.

Thanks for your time.

Edit

This is the usual execution step (when load() is not called):

_thinker.setState();
_thinker.start();
//when _thinker finished()
autoMove();
    > _thinker.setState();
    > _thinker.start();

When load() is called:

_thinker.setState();
_thinker.start();
load();
    > _thinker.setState();
    > _thinker.start();
//when _thinker finished()
autoMove(); // this is the feedback for previous or current state
    > _thinker.setState();
    > _thinker.start();

Note, load() causes _thinker to restart. Now, where to put a boolean check so that autoMove() should ignore ONLY ONCE?

A: 

Not exactly a best practice, but why don't you mark with a bool (use mutexes if neccesary) that the state has changed during execution and, if so, just restart the thread in autoMove (don't provide any feedback).

Update: I was thinking something like:

autoMove() 
{ 
    .... 
    if (!_thinker.stateChanged())  
    {
       // provide feedback
    } 
    //restart _thinker -> on restart _thinker.isStateChanged = false;

 }

Of course, if the user changes the state to often, you may never reach the provide feedback branch :P

This is the usual execution step (when load() is not called):_thinker.setState();_thinker.start();//when _thinker finished()autoMove(); > _thinker.setState(); > _thinker.start();When load() is called:_thinker.setState();_thinker.start();load(); > _thinker.setState(); > _thinker.start();//when _thinker finished()autoMove(); // this is the feedback for previous // or current state > _thinker.setState(); > _thinker.start();Note, load() causes _thinker to restart. Now, where to put a boolean check so that autoMove() should ignore ONLY ONCE?
Donotalo
Oh, the formatting broke up. I'm reposting it in the original post.
Donotalo
+1  A: 

How about using an integer id to determine which state has been computed, to see if it's still valid when computation has finished?

Marcus Lindblom