Trying to use QFuture and QFutureWatcher for the first time
-
OK I've reduced the replication to a relatively simple case:
You can find the source files here:
http://www.perdrix.co.uk/TestQtConcurrent.zipIf you want the entire MSVC solution, say so and I will zip that up and make it available.
David -
OK I've reduced the replication to a relatively simple case:
You can find the source files here:
http://www.perdrix.co.uk/TestQtConcurrent.zipIf you want the entire MSVC solution, say so and I will zip that up and make it available.
David -
OK I've reduced the replication to a relatively simple case:
You can find the source files here:
http://www.perdrix.co.uk/TestQtConcurrent.zipIf you want the entire MSVC solution, say so and I will zip that up and make it available.
David@Perdrix said in Trying to use QFuture and QFutureWatcher for the first time:
You can find the source files here:
http://www.perdrix.co.uk/TestQtConcurrent.zipIf I just open it in Chrome nothing happens.
If I force it to download (it seems to start but never finishes) I get about 4k and then it stops.
If you want someone to access this then please verify it works for you from an incognito browsing session....
UPDATE OK, although the download does not finish properly if I rename the temporary.crdownloadfile to.zipit seems to have content.... -
OK I've reduced the replication to a relatively simple case:
You can find the source files here:
http://www.perdrix.co.uk/TestQtConcurrent.zipIf you want the entire MSVC solution, say so and I will zip that up and make it available.
David@Perdrix
So I have copied/pasted the 3 files you supply into their own project.I don't even see how what you have supplied would compile. In
griddata.hthere are two errors:- No template named
QPromise - Use of undeclared identifier
std
These are both visible in Creator. And make sense to me, as the necessary includes are not in
griddata.h. That is improved with the addition of#include <QPromise>in griddata.h. (And I had to comment out a couple of other includes.)Now I think I am down to a couple of compilation error messages like you have been showing. I will investigate further... :)
The zip file is only 4kB...
I know! But for whatever reason my Chrome does not complete the download of this file from you. It seems to get the full content but never sees it finish, so does not rename the temporary download file to the intended .zip. But doing that manually I seem to have the full zip so I am good.
- No template named
-
Don't need a template GridData only uses a reference: QPrimose<void>& promise but won't harm to include it.
Don't need to do anything for std:: stuff, so long as you call it out by its full name
@Perdrix said in Trying to use QFuture and QFutureWatcher for the first time:
void interpolate(QPromise<void>& promise, const std::vector<double>& x, const std::vector<double>& y, const std::vector<double>& z, const std::vector<double>& xg, const std::vector<double>& yg, std::vector<double>& zg, InterpolationType type, float data = 0.0);All the other
std::vector<double>&s areconst, but not the finalzgone. Intended or not? This is the error.If you make that one
consttoo it compiles.If you test just
void GridData::interpolate2(QPromise<void>& promise, const std::vector<double> &x) QFuture<void>future2 = QtConcurrent::run(&GridData::interpolate2, instance.get(), xValues);That works. But take out the
constand it fails.You could have reduced it down to just this parameter type, nothing to do with all the member methods:
void func1(QPromise<void>& promise, std::vector<double> &xValues) { } QFuture<void> fut1 = QtConcurrent::run(func1, xValues);std::vector<double> &xValuesdoes not pass. Either (or both) of adding inconstor removing the&do pass.I don't use
std::vectorand am going leave it to you now. You may need e.g. @Christian-Ehrlicher to explain the deep reason. I am not sure anyway about accessing non-const reference to arrays in the thread(s) run byQtConcurrent. As I wrote, if you can change yours toconst std::vector<double>& zgorstd::vector<double> zgit won't matter. Though of course we would like to hear from a C++ expert for the definitive explanation!Phew!
And, yes, no, C++ compiler errors, especially with templates, are not the simplest.
P.S.
Just this fails in same way:void func1(QPromise<void>& promise, int &test) { } int test; QtConcurrent::run(func1, test);And again changing
func1()to eitherconst int &testorint testworks. So nothing to do withstd::vector. You evidently cannot pass a mutable reference parameter here, I am thinkingQtConcurrent::run()does not allow this because of threading/need to copy requirements? Now that we knows this is the issue we find e.g.
https://stackoverflow.com/questions/25091518/qt-concurrent-run-pass-value-by-reference-but-the-memory-address-is-differentQtConcurrent::run creates internal copies of all arguments that you pass to it. Your thread function is then given access to these copies, not to the original arguments. Passing something by raw reference does not prevent creation of a copy. In other words, QtConcurrent::run enforces pass-by-value semantics internally.
The address that you see in the ref function is the address of that internal copy.
For this reason, if you specifically want access to the original object, instead of a naked reference you have to use something with pointer semantics or with "copyable reference" semantics.
That was a few years ago. Perhaps the definitions/compiler now show an attempt to pass a non-const reference as a compile-time error where it used to get through but then did not act as expected?
-
Argh! I need that to be a non const vector reference, as the interpolate code populates that vector.
@JonB Thanks for finding out what was stopping it working! I'd never have guessed that was the problem.
I've updated the files so it should compile OK on Linux, and refreshed the zip file:
http://www.perdrix.co.uk/TestQtConcurrent.zip
@Christian-Ehrlicher Can you advise please?Meantime I will change the code to use std::ref(zgEccentricity).
UPDATE: using std::ref(zgEccentricity) worked fine. May I suggest that some documentation updates to say you can't pass a non-const thing using a normal reference and that using std::ref might be useful. Either that or?
David -
Argh! I need that to be a non const vector reference, as the interpolate code populates that vector.
@JonB Thanks for finding out what was stopping it working! I'd never have guessed that was the problem.
I've updated the files so it should compile OK on Linux, and refreshed the zip file:
http://www.perdrix.co.uk/TestQtConcurrent.zip
@Christian-Ehrlicher Can you advise please?Meantime I will change the code to use std::ref(zgEccentricity).
UPDATE: using std::ref(zgEccentricity) worked fine. May I suggest that some documentation updates to say you can't pass a non-const thing using a normal reference and that using std::ref might be useful. Either that or?
David@Perdrix said in Trying to use QFuture and QFutureWatcher for the first time:
Argh! I need that to be a non const vector reference, as the interpolate code populates that vector.
You have just crossed with my final update to my reply. Have a read through the stackoverflow post (or try to find your own), there may be stuff there which allows you to do something, e.g.
QtConcurrent::run(func1, std::ref(test));seems to compile against
int &test, I don't know anything aboutstd::ref()but it looks good?P.S.
Being an originally C person, without all this C++ nonsense, references etc. I betvoid func1(QPromise<void>& promise, int *test) {} QtConcurrent::run(func1, &test);would work ;-) [But of course don't do this!]
-
I found the line about the use of std::ref in the docs, so it is there, but it is fairly easy to miss it.
D.
-
It is buried in the "Additional API Features" section of the doc and says:

It should be right up front where QtConcurrent::run() is described, saying very clearly that you must use std:ref(variable) when passing a reference to a modifiable object.
-
It is buried in the "Additional API Features" section of the doc and says:

It should be right up front where QtConcurrent::run() is described, saying very clearly that you must use std:ref(variable) when passing a reference to a modifiable object.