I am familiarizing myself with QtConcurrent library. I have a UI (MainWindow
) where I run my functions to simulate a real world example of multithreading.
The QtConcurrent::map() function I am using requires some:
- Iterator or a Sequence, in my case I am using a QList.
- Further, it requires a MapFunctor (which supports lambdas*) but for this purpose, I am choosing to stick to a static method for testing.
What I have tried
I attempted using both map() functions (the first is left uncommented)
- QtConcurrent::map(Sequence &sequence, MapFunctor function
- QtConcurrent::map(Iterator begin, Iterator end, MapFunctor function)
I tried searching for a Sequence and a MapFunctor, but I could only find it in templates which did not help alot, thus I had to try and use my intuition to make sense of it.
The Code:
Somewhere inside my MainWindow.cpp
// counter variable stored in MainWindow
int i = 0;
// MapFunctor
void mapSumToQString(QPair<int, int> pair)
{
i++;
qDebug() << "Execute " << i << " = " << QString::number(pair.first, pair.second);;
}
and the code to start it all
// UI class decl
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create list of integers to perform map function on (here I don't write back to the original sequence i.e. list)
QList<QPair<int, int>> intPairList = QList<QPair<int, int>>();
for (int i = 0; i < 1000; i++) {
int i1 = qrand();
int i2 = qrand();
intPairList.append(QPair<int, int>(i1, i2));
}
QFuture<void> future;
future = QtConcurrent::map(intPairList, mapSumToQString);
// future = QtConcurrent::map(intPairList.begin(), intPairList.end(), mapSumToQString);
}
Problem:
Running this snippet of code results in a SEGV here
namespace QtConcurrent {
// map kernel, works with both parallel-for and parallel-while
template <typename Iterator, typename MapFunctor>
class MapKernel : public IterateKernel<Iterator, void>
{
MapFunctor map;
public:
typedef void ReturnType;
MapKernel(Iterator begin, Iterator end, MapFunctor _map)
: IterateKernel<Iterator, void>(begin, end), map(_map)
{ }
bool runIteration(Iterator it, int, void *) override
{
map(*it); <--------SEGV line
return false;
}
//...
}
Stacktrace (copied from debugger)
1 QtConcurrent::MapKernel<QList<QPair<int, int>>::iterator, QtConcurrent::FunctionWrapper1<void, QPair<int, int>>>::runIteration qtconcurrentmapkernel.h 68 0x404ee8
2 QtConcurrent::MapKernel<QList<QPair<int, int>>::iterator, QtConcurrent::FunctionWrapper1<void, QPair<int, int>>>::runIterations qtconcurrentmapkernel.h 77 0x404f82
3 QtConcurrent::IterateKernel<QList<QPair<int, int>>::iterator, void>::forThreadFunction qtconcurrentiteratekernel.h 255 0x40466e
4 QtConcurrent::IterateKernel<QList<QPair<int, int>>::iterator, void>::threadFunction qtconcurrentiteratekernel.h 217 0x404486
5 QtConcurrent::ThreadEngineBase::run qtconcurrentthreadengine.cpp 302 0x6d881973
6 QThreadPoolThread::run qthreadpool.cpp 99 0x111b36a
7 QThreadPrivate::start(void *) *4 qthread_win.cpp 403 0x11163eb
8 KERNEL32!BaseThreadInitThunk 0x74d56359
9 ntdll!RtlGetAppContainerNamedObjectPath 0x77467c24
10 ntdll!RtlGetAppContainerNamedObjectPath 0x77467bf4
11 ??
For the record, there is another question related to this, but most certainly does not provide a usable solution.
Why do I get this SEGV, what is causing this access violation?
Honestly, some parts of your question are not clear for me. However, please take into account the followings (although you may have considered some or all of them):
and modify the implementation as follows:
mapSumToQString
is static, hence you cannot use non-static members of theMainWindow
inside it. Hence, thei
must be static as well.