Reputation: 30915
i have thread pool that create threads each thread worker calculate some work and when it done
it writes the result to file , there is only 1 result file , that each worker thread needs to write to .
now my question is how i guarantee that there wouldn't be any locks or missing write data to the file where allot of threads trying to write to single file ? what is the right strategy for such scenario?
mybe keep all result in memory ? or chanks of results
im using already the QThreadPool framework , and i need to find solution with it.
also i wander , does writing to single file from worker threads , i will have to use
singleton file manager or static class , is it good idea? for multithreaded app ?
Upvotes: 0
Views: 5195
Reputation: 5714
So you have many concurrent threads competing for one shared resource. That begs a synchronization primitive of some sort, for example a mutex.
Here's (non-Qt specific) code showcasing 10 threads simultaneously writing to a single file. On a side note, C++11 introduced a lot of goodies like std::mutex
(and std::thread
too, so that can help eliminate some Qt-specific threading code).
#include <fstream>
#include <mutex>
#include <thread>
#include <vector>
std::mutex m;
std::ofstream file;
int main() {
file.open("file.txt");
std::vector<std::thread> workers;
for (int i = 0; i < 10; ++i) {
workers.push_back(std::thread([=i] {
for (int j = 0; j < 10; ++j) {
std::lock_guard<std::mutex> lock(m);
file << "thread " << i << ": " << j << endl;
}
}));
}
for (auto& worker : workers) {
worker.join();
}
file.close();
return 0;
}
Of course, if you have a lot of places in your code accessing the shared resource, it's better to encapsulate it, along with the mutex, in some "accessor" class that would manage all state-modifying calls to the resource.
P.S. If you're not on C++11 compiler, you can use boost::mutex
or Qt-specific mutex wrapper. The key thing is that you need some synchronization primitive associated with the shared resource.
Upvotes: 8
Reputation: 12547
As I assume, you crate your own Runnable
, deriving from QRunnable
You can pass some context information when constructing your Runnable
class. You need to pass device to write in and mutex
to lock device, for example.
class Runnable: public QRunnable
{
public:
Runnable(QIOdevice* device, QMutex* mutex):_d(device), _m(mutex){}
void run()
{
saveInFile();
}
private:
void saveInFile()
{
QMutexLocker lock(_m);
//now only one thread can write to file in the same moment of time
device->write(...);
}
QIOdevice* _d;
QMutex* _m;
};
Upvotes: 2