Problem synchronizing QThreads - c++

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.
_thinker starts, with states say, s0.
User loads another state from file, say s1.
_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?

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

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

Related

What is triggering "ASSERT failure in QCoreApplication::sendEvent" here?

I'm getting this error: ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x20e51b65eb0. Receiver 'gw2g' (of type 'gw2g') was created in thread 0x0x20e4fd0c930"
DEBUG:
MAIN_thread started: QThread(0x20e4fd0c930)
DUMMY_LOOP started: QThread(0x20e51b65eb0)
What could cause this error?
gw2g.cpp
addExtenders()
{
//...model gets set etc
//
connect(this, SIGNAL(xprep_ready(bool)), ui->connectButton, SLOT(setEnabled(bool)), Qt::AutoConnection);
connect(ui->listView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(prep_connectx(QItemSelection)), Qt::AutoConnection);
}
While debugging with breakpoints I found out that I get this error after leaving addExtenders()
I also set breakpoints inside destructor of dummyMain_c and gw2g, neither gets destroyed unwantedly. Sometimes dummyMain_c does get destroyed unexpectedly.
(Press Retry to debug the application)
QCoreApplication::exec: The event loop is already running
Maybe it has something to do with this event_loop
emit extend_list();
wait_xcon.exec();
It gets quit when clicking one of the buttons in the GUI.
QObject::connect(mwindow.ui->connectButton, &QPushButton::clicked, &dummy_main.wait_xcon, &QEventLoop::quit);
I don't even get to that part though unfortunately.
the threads in the picture are the main (0x0x2059fdfd9b0) and the dummy (0x0x205a1c85ff0)
I also checked if all main window functions run in the main thread - they do.
So all GUI stuff happens in the main - I don't know anymore.
I figured it out.
The error message was very misleading, since the problem was the QEventLoop in dummy.
When main window(gw2g) QPushButton is clicked it quits this eventloop, so why is the receiver (gw2g)?
So, I just got rid of
wait_xcon.exec();
and replaced it with a simple
while(!quitloop){}
clicking the button now sets this bool to true

QtConcurrent mapped and progress report

I'm using QtConcurrent to do some heavy background image processing and I want to display the image while parts of it are being updated progressively.
Each line of the image is computed separately and is passed a functor.
To compute the full image I then have a sequence of item that I pass to QtConcurrent mapped and each line emits a signal when it is done computing
Here is the instantiation of the class Worker:
//living in the main(gui) thread !
Worker::Worker(VideoEngine* engine):_engine(engine){
_watcher = new QFutureWatcher<bool>;
_watcher->setPendingResultsLimit(200);
connect(_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(onProgressUpdate(int)));
connect(_watcher, SIGNAL(finished()), engine, SLOT(engineLoop()));
}
Here is the slot to report progress:
void Worker::onProgressUpdate(int i){
if(i < (int)_rows.size() && i%10==0){
cout << " index = " << i << " y = "<< _rows[i] << endl;
_engine->checkAndDisplayProgress(_rows[i],i);
}
}
Now the usage:
void Worker::_computeTreeForFrame(.../*unrelevant args*/){
....
....
_watcher->setFuture(
QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output)));
}
}
All the signals are emitted but the slot onProgressUpdate gets called only when Qtconcurrent::mapped is done with all the items in the sequence.
When executing it has a huge delay while the sequence is processing and then all slots are executed sequentially afterwards.
I have tried all types of signal/slots connection and none of them changed this behaviour.
Any clue ?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EDIT after Shf suggestion
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The call was made until now in the main(gui) thread.
I changed the call to :
_computeFrameWatcher->setFuture(QtConcurrent::run(_worker,&Worker::computeTreeForFrame));
Since _computeTreeForFrame is now executed in another thread, I changed the call to QtConcurrent::mapped to:
_watcher->setFuture(QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output)));
_watcher->waitForFinished();
This results in exactly the same behaviour as before.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EDIT after Marek R suggestion
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ok so I made so tests and here is what I observed:
QtConcurrent::map :
Doesn't emit the signal resultReadyAt(int)
QtConcurrent::mapped
Emits resultReadyAt(int) only when finished
It doesn't matter if the call to the map function is done in a separate thread the same behaviour is encountered.
I also gave a try to the signal progressValueChanged(int) as the Qt progressDialog example suggests.
The signal progressValueChanged(int) gets emitted only for 2 lines in the image (the first and last).
This is really weird as in the Qt progress dialog example it is emitted smoothly.
I changed a bit the Qt example to launch the map function in another thread than the main thread and it still works well in that case.
The issue must arise from somewhere else.
Maybe the GUI event loop is doing something I don't expect ? I have no clue what.
I will now try QtConcurrent::mappedReduced and report with the results :-)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EDIT after giving a try to QtConcurrent::mappedReduced
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
It doesn't work and calls the "reduce" function ONLY when the "map" function is done. In other words it does the same than the previous signal/slots mechanism.
I'm running low in possibilities now
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EDIT I'm back to a solution as close as the Qt progress dialog example
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Something must be wrong if I can't get the same behaviour than the Qt example.
Here's the code now:
//created in the main thread! (gui)
Worker::Worker(VideoEngine* engine):_engine(engine),_watcher(0){
_watcher = new QFutureWatcher<void>;
_watcher->setPendingResultsLimit(200);
connect(_watcher,SIGNAL(progressValueChanged(int)), _engine,
SLOT(onProgressUpdate(int)));
connect(_watcher, SIGNAL(finished()), engine, SLOT(engineLoop()));
}
//executed on the main thread
void Worker::computeTreeForFrame(...){
...
_watcher->setFuture(QtConcurrent::map(_sequence,boost::bind(metaEnginePerRow,_1,output)));
...
}
The call to computeTreeForFrame...
...
_worker->computeTreeForFrame();
...
This call is done in a slot .
It emits the signals for the line 0 and for the last line as told before but doesn't emits anything else.
Shouldn't this do EXACTLY what the Qt example does?
From task description it looks like you should use mappedReduced. Problem is that I don't see a good way to get partial results. One way to overcome this problem is to emit signal form reduce function.
It is possible that this thread may help.
It seems, that QtConcurrent::mapped does not put VideoEngine::metaEnginePerRow in another thread, judging by the documentation. If image is processed in the same thread as GUI, then your slots indeed will be executed after processing, no matter what type of connection you select, just as you've described.
The solution is to either run Worker::_computeTreeForFrame (as i understood, your main processing function) in another thread via QtConcurrent::run or to put your Worker object in another thread probably via QObject::moveToThread(). Then, the connection type you should use is Qt::QueuedConnection (or if you will put Worker in another thread before connection, you can connect even with Qt::AutoConnectionor Qt::UniqueConnection, caller and receiver will be in a different threads, so qt will automaticly chose QueuedConnection`)
EDIT:
I'm not sure, but your _watcher = new QFutureWatcher<bool>; is still created in the main thread and if you call
_watcher->setFuture(QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output)));
_watcher->waitForFinished();
would _watcher set GUI thread to wait, in what it was created or thread, where this command is executed. If _watcher->setFuture(QtConcurrent::mapped(_sequence,
boost::bind(&VideoEngine::metaEnginePerRow,_1,output))); if the end of a function, is _watcher->waitForFinished(); needed at all? Qt will destroy thread right after it's execution and you set your processing function to run, why wait?
And _computeFrameWatcher should be of QFuture<void*> type.
EDIT2:
Ok, before i give up, i suggest you to test QObject::moveToThread:
before you call _worker->computeTreeForFrame(); , put it in another thread:
QThread *workerThread=new QThread();
_worker->moveToThread();
_worker->computeTreeForFrame();
/* connect _worker's finished signal with workerThread::quit and deleteLater slots */
and all connections within _worker should be DirectConnection and all connections between _worker and main (GUI) thread should be connected with QueuedConnection. Also it's probably good to create new thread in _worker constructor and move it to another thread immediately, this way you can destroy thread in _worker's destructor and don't worry about thread problem's in GUI thread

How to lock code execution in iOS application

Problem Description
I have a function StdString ShowLockScreen() in this function I call activateViewController function which shows some UI where user must enter PIN, just after calling activateViewController function I want to lock all processes until user will enter his PIN and press OK button on opened UI. Below you can see code which I try
Source code in iOS
StdString ShowLockScreen()
{
// Create a lock.
NSLock* theLock = [[NSLock alloc] init];
// Create a UI in which user must enter his PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
// Set delegate.
controller.delegate = m_Context;
// !!! Here I show a UI and just after that I lock my lock in order code stop executing there.
[controller activateViewController:nil];
#synchronized(theLock) {
[theLock lock];
}
NSLog(#"User in UI unlock the lock");
}
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing. But it doesn't work in my case.
Source code in Android
I have write similar application in Android and here is code. I want to write same in iOS but I can;t find solution
Intent intent = new Intent(mCtx, SoftPinActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedObject lock = new SharedObject("");
int lockId = SharedObject.acquireLockId(lock);
Logger.i(TAG, "lockId = " + lockId);
intent.putExtra(SharedObject.LOCK_ID, lockId);
intent.putExtra(SoftPinActivity.UI_ID, style);
synchronized (lock) {
mCtx.startActivity(intent);
try {
Logger.i(TAG, "lock.wait()...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Logger.i(TAG, "InterruptedException");
}
}
Logger.i(TAG, "lock.wait()...done");
SharedObject.releaseLockId(lockId);
String pin = lock.object();
Researches
I think I must use
NSCondition* condLock = [[NSCondition alloc] init];
[condLock wait];
and
[condLock signal];
but how to use this in my code ?
Answer to problem
You can lock threads using NSLock, but in your situation, this doesn't seem to be applicable. The reason being is that locking is primarily used to provide thread safety when data is accessed from multiple threads. What you're asking for is a domain level lock, which prevents the user from using the application unless they've typed in their PIN. These two concepts share the word "lock", but they're entirely different in their implementation. If you were to use NSLock and its related counterparts, you're forcing your implementation into separate threads purely to block user interaction, and risk complicating your project and pains in debugging (deadlocks much?).
Suggested solution
As the concept is a domain level locking mechanism, I suggest we keep it this way for its implementation. If you want it to be analogous to Android, then you'd need to create your own concept of a 'SharedObject' that everything else queries. If this object were to say "The user hasn't unlocked the application", then nothing will process. This keeps you away from manually managing threads, and frees threads up for when you really need them most (asynchronous processing for example).
To implement this object, lets call it a UserContext, which is available as a singleton. How to implement this sharedInstance can be seen here.
Once you have that, then you can add various properties to it that are global throughout the application (and by the suggestion of the name, has all global properties that belong to a particular user). One of these properties is whether the user has the app locked or not:
[[UserContext sharedInstance] isLocked] // Returns BOOL
Using this throughout your application, you can then control (at the domain concept level), whether a method can compute something or not (naturally, you'll need to make UserContext thread safe, as it could be queried anywhere at any time). It would make it clear to the developer reading the code, that a certain method can not do anything unless the user has unlocked the app. To stop
Side notes
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing.
Do not, under any circumstances, lock the UI thread. In a published app, the watchdog will kill your app, and it will effectively crash.
ViTo, as much I concerned with the NSLock, we use it in the case of multi-threading in which we lock a particular thread and force that upto that not unlock, none other thread become active or to do his required task.
So, may be what we can do that first of all we start all of your processes in the terms of thread and at that point when you try to open your UI we call 'lock' and when user pressed the button after inputting the text-box then we call 'unlock'.
But, for this we've to sure that this thread has high priority.
That's what I'm thinking right now, but really try this with my sample code and will update you accordingly.
Check that part of code:
+(void)aMethod:(id)param{
int x;
for(x=0;x<50;++x)
{enter code here
[lock lock];
printf("Object Thread says x is %i\n",x);
usleep(1);
[lock unlock];
}
}
- (void)viewDidLoad
{
int x;
lock = [[NSLock alloc] init];
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MViewController class] withObject:nil];
for(x=0;x<50;++x)
{
[lock lock];
printf("Main thread says x is %i\n",x);
usleep(10000);
printf("Main thread lets go %i\n",x);
[lock unlock];
usleep(100);
}
printf("Now getting the process");
[super viewDidLoad];
}
Check the log you'll get what you want.
Hope, it's what you need. For any concern, shout-over me.
Okay I found solution to this issue, below you can see implemented function and line by line description.
StdString ShowLockScreen()
{
// Create NSCondition lock object.
NSCondition* conditionLock = [[NSCondition alloc] init];
// Here I create my UI which must ask user to enter PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
controller.delegate = m_Context;
// Here I lock the thread but not main thread (this is very important) I start
// ShowLockScreen function in new thread and lock it.
[conditionLock lock];
dispatch_sync(dispatch_get_main_queue(), ^{
// I call function which shows my UI in main thread as UI can be shown
// only in MAIN THREAD. (This is important too.)
[controller ShowLockController:conditionLock];
});
// Then I set lock to wait, how you can see I pass conditionLock as an
// argument to ShowLockController function in that function when user
// enter his PIN and press okay button I call [conditionLock signal];
// and my code code here after wait and continue executing.
[conditionLock wait];
NSLog(#"Come here then I call [conditionLock signal]!!!")
}

qt signals/slots in a plugin

I have an app with such structure: all the datatypes (class INode) are stored in plugins (DLLs). Some of the datatypes can be drawn (if they're IDrawable).
To load an object of, e.g. class PointCloudNode: public INode I have a special input plugin (DLL) which is called class PointCloudParser: public IIOPlugin and IIOPlugin is a thread with some specific functionality: class IIOPlugin: public QThread.
All the objects are created by NodeFactory class which is a singleton stored in separate DLL.
And here's the problem:
void PointCloudNode::update()
{
QObject::connect (this,SIGNAL(tmptmp()),this,SLOT(drawObject()));
emit tmptmp();
}
If I do this from any thread (main thread or the Input Plugin thread)
NodeFactory* fab = NodeFactory::getInstance();
boost::shared_ptr<INode> pc(fab->createNode("pointCloud","myPC"));
boost::shared_ptr<IDrawable> dr = boost::dynamic_pointer_cast<IDrawable>(pc);
dr->update();
The update launches, the tmptmp() signal is emitted, and the slot (drawObject()) executes correctly.
BUT
if do just the same, but create the object in my Input Plugin, pass over the shared pointer and execute dr->update() in another function, the slot drawObject() is never entered though all the code is executed (including connect, etc.).
To be more precise, here's the Input Plugin:
void PointCloudParserPlugin::doLoad(const QString& inputName, boost::shared_ptr<INode> container)
{
NodeFactory* factory = NodeFactory::getInstance();
boost::shared_ptr<INode> node = factory->createNode("pointCloud", inputName);
// here goes the loading itself, nothing special...
container->addChild(node); //that's the container where I keep all the objects
//boost::dynamic_pointer_cast<IDrawable>(container->getChild(inputName))->update();
//If I uncomment this line, it all works: the slot is launched.
emit loadingFinished(inputName); // it executes the following function
}
The last emit is connected to this:
void GeomBox::updateVisualization(const QString& fileName)
{
boost::shared_ptr<INode> node = container_->getChild(fileName);
boost::shared_ptr<IDrawable> nodeDrawable = boost::dynamic_pointer_cast<IDrawable>(node);
nodeDrawable->update(); //this is the problem line: update() executes, connect() works, but the slot never runs :(
}
How come? The node object is the same all the way through, it is valid. Every line in code in launched, QObject::connect doesn't write anything to debug window, the signal tmptmp() is emitted, but the slot drawObject() in one case is never reached? Any ideas?
Upd.: If I do not inherit IIOPlugin from QThread, everything works fine (i.e. load the object in the main thread). I expected the signals/slots to work across the threads...
Since you are sending a signal across to a different thread, you might need to explicitly tell Qt that the connection should be a queued one:
QObject::connect(this, SIGNAL(tmptmp()), this, SLOT(drawObject()), Qt::QueuedConnection );
By default Qt will use Qt::AutoConnection as that last parameter, and it will choose whether to use a direct connection (if the slot is in the same thread as the emitter) or a queued connection (if the slot is in a different thread). But since your thread is in a separate library, maybe Qt isn't making the right assumption here.

Execute some operation after the thread is completed

Greetings, everyone!
I have a class (say, "Switcher" ) that executes some very-very long operation and notifies its listener, that operation is complete. The operation is long, and I isolate actual switching into separate thread:
class Switcher
{
public:
// this is what other users call:
void StartSwitching()
{
// another switch is initiated, I must terminate previous switching operation:
if ( m_Thread != NULL )
{
if ( WaitForThread(m_Thread, 3000) != OK )
{
TerminateThread(m_Thread);
}
}
// start new switching thread:
m_Thread = StartNewThread( ThreadProc );
}
// this is a thread procedure:
static void ThreadProc()
{
DoActualSwitching();
NotifyListener();
}
private:
Thread m_Thread;
};
The logic is rather simple - if user initiates new switching before the previous one is complete, I terminate previous switching (don't care of what happens inside "DoActualSwitching()") and start the new one. The problem is that sometimes, when terminating thread, I loose the "NotifyListener()" call.
I would like to introduce some improvements to ensure, that NotifyListener() is called every time, even if thread is terminated. Is there any pattern to do this? I can only think of another thread, that infinitely waits for the switcher and if the switcher is done (correctly or by termination), it can emit notification. But introducing another thread seems an overplay for me. Can you think of any other solution (p.s. the platform is win32)?
Thank you!
First, you should never call TerminateThread. You cannot know which operation is terminated when calling TerminateThread and so that could lead to memory leaks/resource leaks/state corruption.
To get your thread to be interruptable/cancelable, you supply a 'cancel' state, which is checked by the thread itself. Then your notify end will always work.
TerminateThread() here whacks the thread, and if it was inside DoActualSwitching(), that's where it'll die, and NotifyListener() will not be called on that thread. This is what TerminateThread() does, and there is no way to make it behave differently.
What you are looking for is a bit more graceful way to terminate the thread. Without more info about your application it's difficult to suggest an optimal approach, but if you can edit DoActualSwitching(), then I'd add
if (WAIT_OBJECT_0 == WaitForSingleObject(m_ExitThreadEvent, 0))
break;
into the loop there, and call SetEvent(m_ExitThreadEvent) instead of TerminateThread(). Of course you'll need to create the event and add the handle to the class. If your model suggest that there is only one switching thread at a time, I'd use autoreset event here, otherwise some more code is needed.
Good luck!