Your problem is a classical concurrent data analysis problem. Have you tried using std::mutex
? Here's how you use it:
You create some variable std::mutex
(mutex = mutual exclusion) that's accessible by all the relevant threads.
std::mutex myLock;
and then, let's say that the function that processes the data looks like this:
void processData(const Data& myData)
{
ProcessedData d = parseData();
insertToDatabase(d);
}
Now from what I understand, you're afraid that multiple threads will call insertToDatabase(d)
simultaneously. Now to solve this issue, simply do the following:
void processData(const Data& myData)
{
ProcessedData d = parseData();
myLock.lock();
insertToDatabase(d);
myLock.unlock();
}
Now with this, if another thread tries to access the same function, it will block until another all other threads are finished. So threads are mutually excluded from accessing the call together.
More about this:
Caveats:
This mutex object must be the same one that all the threads see, otherwise this is useless. So either make it global (bad idea, but will work), or put it in a the class that will do the calls.
Mutex objects are non-copyable. So if you include them in a class, you should either make the mutex object a pointer, or you should reimplement the copy constructor of that class to prevent copying that mutex, or make your class noncopyable using delete
:
class MyClass
{
//... stuff
MyClass(const MyClass& src) = delete;
//... other stuff
};
There are way more fancier ways to use std::mutex
, including std::lock_guard
and std::unique_lock
, which take ownership of the mutex and do the lock for you. This are good to use if you know that the call insertToDatabase(d);
could throw an exception. In that case, using only the code I wrote will not unlock the mutex, and the program will reach a deadlock.
In the example I provided, here's how you use lock_guard
:
void processData(const Data& myData)
{
ProcessedData d = parseData();
std::lock_guard<std::mutex> guard(myLock);
insertToDatabase(d);
//it will unlock automatically at the end of this function, when the object "guard" is destroyed
}
Be aware that calling lock()
twice by the same thread has undefined behavior.
Everything I did above is C++11.
If you're going to deal with multiple threads, I recommend that you start reading about data management with multiple threads. This is a good book.
If you insist on using Qt stuff, here's the same thing from Qt... QMutex.