[ fromfile: threads.xml id: parallellife ]
Example 17.23. src/threads/life/lifeslice.h
Example 17.24. src/threads/life/lifemainwindow.cpp
[ . . . . ] struct LifeFunctor : public std::unary_function<LifeSlice, LifeSlice> { LifeSlice operator() (LifeSlice slice); }; LifeSlice LifeFunctor::operator()(LifeSlice slice) { QRect rect = slice.rect; QImage image = slice.image; QImage next = QImage(rect.size(), QImage::Format_Mono); next.fill(DEAD); int h = rect.height(); int w = rect.width(); for (int c=0; c<w; ++c) { for (int r=0; r<h; ++r) { int x = c+rect.x(); int y = r+rect.y(); bool isAlive = (image.pixelIndex(x, y) == ALIVE); int nc = neighborCount(image, x, y); if (!isAlive && nc == 3) next.setPixel(c, r, ALIVE); if (!isAlive) continue; if (nc == 2 || nc == 3) next.setPixel(c,r, ALIVE); } } slice.image = next; return slice; }
Deriving a unary function object, LifeFunctor
from the Standard Library template unary_function
gives our functor additional type "traits", used by generic algorithms to get the argument and return type of the functor.
This functor defines an operator()
that takes a LifeSlice
argument and returns a LifeSlice
value.
Example 17.25. src/threads/life/lifemainwindow.cpp
The main loop Example 17.26 must break up the problem into smaller pieces, send them to a QtConcurrent blockingMappedReduced()
, and send the results to the LifeWidget
.
Example 17.26. src/threads/life/lifemainwindow.cpp
[ . . . . ] void LifeMainWindow::calculate() { int w = boardSize.width(); // This might not be optimal but it seems to work well... int segments = QThreadPool::globalInstance()->maxThreadCount() * 2; int ws = w/segments; LifeFunctor functor; while (m_running) { qApp->processEvents(); m_numGenerations++; QList<LifeSlice> slices; for (int c=0; c<segments; ++c) { int tlx = c*ws; QRect rect(tlx, 0, ws, boardSize.height()); LifeSlice slice(rect, m_current); slices << slice; } m_current = QtConcurrent::blockingMappedReduced(slices, functor, stitchReduce, QtConcurrent::UnorderedReduce ); m_lifeWidget->setImage(m_current); } }
The qApp->processEvents()
is required in this loop for the main event loop to receive and process other GUI events.
If you comment that line out and try running the application, you notice that as soon as the calculations start, there is no way to stop or quit.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |