Solved Concurrent map equivalent
-
@Defohin said in Concurrent map equivalent:
Using QtConcurrent::map won't work cause I can't pass additional arguments.
Just use a function object
struct MapHelper{ MapHelper(){} QString m_additionalArgument1; QString m_additionalArgument2; typedef QString result_type; QString operator()(const QString &val) { return m_additionalArgument1+val+additionalArgument2; } } MapHelper helper; // TODO: make sure to manage its lifecycle helper.m_additionalArgument1 = "Prefix "; helper.m_additionalArgument2 = " Suffix"; QtConcurrent::map(list_of_names,helper);
-
@VRonin How to get the return from each one now?
struct NameHelper { NameHelper(const QString &extra) : _extra(extra) { } typedef QString result_type; QString operator()(const QString &name) { return QString("Hello %1 %2").arg(name).arg(_extra); } QString _extra; }; QStringList names = { "john", "jane" }; QString extra = "doe"; QFuture<QString> example = QtConcurrent::mapped(names, NameHelper(extra));
example.result()
is returning only"Hello john doe"
. -
You can achieve the same with C++11 std::bind:
QString concatenate(const QString& prefix,const QString& val,const QString& suffix){return prefix+val+suffix;} QtConcurrent::mapped(list_of_names,std::bind(concatenate,"Prefix ",std::placeholders::_1," Suffix"));
How to get the return from each one now?
[...]
example.result() is returning only "Hello john doe".use
results()
instead ofresult()
-
It's working nicely, but one last question; Is it GUI blocking? I tried to use a for loop inside of the function and it's now showing anything until it's finished.
-
@Defohin said in Concurrent map equivalent:
Is it GUI blocking?
no, unless you force it to be
I tried to use a for loop inside of the function
could you post the code?
-
struct NameHelper { NameHelper(const QString &extra) : _extra(extra) { } typedef QString result_type; QString operator()(const QString &name) { for(int i = 0; i < 999999; ++i) { qDebug() << "block"; } return QString("Hello %1 %2").arg(name).arg(_extra); } QString _extra; }; QStringList names = { "john", "jane" }; QString extra = "doe"; QFuture<QString> example = QtConcurrent::mapped(names, NameHelper(extra));
-
operator()
will be executed in another thread, it will not block the GUI thread, it will not return until completed (of course) -
@VRonin But why is it not appearing the window If it's running in another thread?
-
@Defohin said in Concurrent map equivalent:
But why is it not appearing the window If it's running in another thread?
WOW! we are taking this on a whole new level here! you need a QFutureWatcher on the QFuture and a slot connected to the
resultReadyAt
signal to display the results in the GUI -
You are a god, thank you.
-
I definitely am not, trust me.
Just as a final remark, in your case, if you can use C++11, I'd use
std::bind
over the function object -
I'm using
std::bind
now... I realized something:
THe threads is not closing if the application closes, meaning that if I close the window it will still open. (if I do a heavy work inside the called function). -
Since you are using
mapped
you can call cancel() to signal to abort the calculation -
@VRonin Do I have to connect that to a signal from the window for when it's closing or something?
-
- If you want to stop the calculation when the widget is closed reimplement the closeEvent and call cancel on the QFuture
- If you want to stop the calculation when the widget is destroyed reimplement the destructor and call cancel on the QFuture
-
@VRonin Thank you very much.