Reputation: 147
I will try to explain what my program used to do and what I am tring to change:
I had this function that ran on a button click from the the main thread in class MainWindow : public QMainWindow :
The function looks like this and is specified inside another file:
void MakeMeshStructure(MeshStructureLayers layers,
Handle_AIS_InteractiveContext theContext,
Handle_TDocStd_Document aDoc,
MyMesh &mesh,
int detail_vertex,
double insulation_thickness,
OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}
What it does is: it works on mesh and creates geometry for every vertex, face and edge of the mesh. This geometry gets displayed with theContext. This process takes very long (30 min) and blocks the gui.
What I would like to do is to have as many threads as QThread::idealThreadCount() and to free the gui when it computes and make it faster. (Is this the right thinking?)
I would like to divide my mesh into equal parts and pass this range of vertices to my function (above) to only work with one vertex range for a seperate tread.
I have a problem to figure out how to pass this data around and to make it thread safe. I know its alot of code but here is my attempt at solving it:
The problem is getting all the data around in the right way and getting the threads to work. Where do I have to use mutexes. On every data that can get writen at the time of the thread work by the mainthread? Very confused. ty
edit:
I edited my code: http://pastebin.com/u/mzagar I made a struct cadData to pass the data around. This is how I start threads:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
//...
emit startMake1(aCadDatas.at(0));
//...
The problem is threads dont seem to work at the same time and also the gui freezes. Process goes in like this:
Any ideas why?
edit2:
I removed the multiple runs of the same thread by moving this to the class constructor:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
Upvotes: 0
Views: 4655
Reputation: 73379
Since you're using QThread, you can probably avoid explicit use of mutexes and such by using Qt's thread-safe slots-and-signals mechanism to do the work for you. You would basically package the data you need to send to the thread into an object, then emit a signal that has that object as an argument. The thread would receive a copy of that object in a slot (that you had previously connected to your signal) and start using the data then. To get data back from the worker thread to the main thread, you'd do the same thing again in reverse. Here's an article with some example code.
Upvotes: 2
Reputation: 98525
To add to Jeremy's answer: You can do the same by sending events between QObjects instead of using the signal-slot mechanism. Use whichever is most convenient for you.
The key is to leverage Qt's built-in event loop mutex. When you're sending signals to objects living in a thread different from the sender, the signal gets converted into a QMetaCallEvent and is posted to the event queue of the receiving QObject. This is done in a thread safe manner of course, and all one has to do is to leverage it. Sending explicit events works the same way. The event loop spinning in the thread where the receiver lives simply picks up QMetaCallEvents and executes slot calls accordingly, or dispatches your events to your implementation of customEvent()
method.
When you start a raw QThread
, the default implementation of the run()
method spins up an event loop. You'll notice that such a thread is effectively idle and does not consume any CPU resources: the event queue is empty, and the event loop is blocked, waiting for someone to post an event to its queue. Once you move some QObjects to such a thread, the queued signal-slot deliveries will be done via the event loop of that thread. It works the same whether it's the GUI thread, or any other thread. The GUI thread is not special in any way when it comes to receiving events or queued signals.
Upvotes: 0