From d930e94c4247faf0333e6056e6e960fdad4054bd Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Thu, 22 Aug 2019 10:57:38 +0300 Subject: [PATCH] Use QtConcurrent::mapped to run nesting. This will allow to use QFutureWatcher and create a barier to wait when all jobs finish. Reduced number of jobs. All piece edges checked in one thread. --HG-- branch : develop --- src/libs/vlayout/vbestsquare.cpp | 7 ++- src/libs/vlayout/vbestsquare.h | 1 + src/libs/vlayout/vbestsquare_p.h | 12 +++- src/libs/vlayout/vposition.cpp | 100 +++++++++++++++++++++++-------- src/libs/vlayout/vposition.h | 17 +++--- 5 files changed, 99 insertions(+), 38 deletions(-) diff --git a/src/libs/vlayout/vbestsquare.cpp b/src/libs/vlayout/vbestsquare.cpp index c3d316167..642285bd4 100644 --- a/src/libs/vlayout/vbestsquare.cpp +++ b/src/libs/vlayout/vbestsquare.cpp @@ -41,6 +41,11 @@ Q_DECL_CONSTEXPR inline qint64 Square(QSizeF size) } } // anonymous namespace +//--------------------------------------------------------------------------------------------------------------------- +VBestSquare::VBestSquare() + : d(new VBestSquareData()) +{} + //--------------------------------------------------------------------------------------------------------------------- VBestSquare::VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait) : d(new VBestSquareData(sheetSize, saveLength, isPortrait)) @@ -111,7 +116,7 @@ void VBestSquare::NewResult(const VBestSquareResData &data) //--------------------------------------------------------------------------------------------------------------------- void VBestSquare::NewResult(const VBestSquare &best) { - if (best.HasValidResult() && d->saveLength == best.IsSaveLength()) + if (best.d->isValid && best.HasValidResult() && d->saveLength == best.IsSaveLength()) { NewResult(best.BestResultData()); } diff --git a/src/libs/vlayout/vbestsquare.h b/src/libs/vlayout/vbestsquare.h index a8fe39017..c9c3d9699 100644 --- a/src/libs/vlayout/vbestsquare.h +++ b/src/libs/vlayout/vbestsquare.h @@ -42,6 +42,7 @@ class VBestSquareData; class VBestSquare { public: + VBestSquare(); VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait); VBestSquare(const VBestSquare &res); virtual ~VBestSquare(); diff --git a/src/libs/vlayout/vbestsquare_p.h b/src/libs/vlayout/vbestsquare_p.h index 3a7a4cf44..5d6947e3e 100644 --- a/src/libs/vlayout/vbestsquare_p.h +++ b/src/libs/vlayout/vbestsquare_p.h @@ -42,8 +42,12 @@ QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor") class VBestSquareData : public QSharedData { public: + VBestSquareData() + {} + VBestSquareData(const QSizeF &sheetSize, bool saveLength, bool isPortrait) - : sheetSize(sheetSize), + : isValid(true), + sheetSize(sheetSize), saveLength(saveLength), isPortrait(isPortrait) { @@ -52,6 +56,7 @@ public: VBestSquareData(const VBestSquareData &res) : QSharedData(res), + isValid(res.isValid), sheetSize(res.sheetSize), valideResult(res.valideResult), saveLength(res.saveLength), @@ -63,9 +68,10 @@ public: ~VBestSquareData() {} - QSizeF sheetSize; + bool isValid{false}; + QSizeF sheetSize{}; bool valideResult{false}; - bool saveLength; + bool saveLength{false}; VBestSquareResData data{}; bool isPortrait{true}; bool terminatedByException{false}; diff --git a/src/libs/vlayout/vposition.cpp b/src/libs/vlayout/vposition.cpp index 053a6a4fb..a0ed76286 100644 --- a/src/libs/vlayout/vposition.cpp +++ b/src/libs/vlayout/vposition.cpp @@ -29,6 +29,8 @@ #include "vposition.h" #include +#include +#include #include #include #include @@ -58,9 +60,13 @@ #include #endif +//--------------------------------------------------------------------------------------------------------------------- +VPosition::VPosition() +{} + //--------------------------------------------------------------------------------------------------------------------- VPosition::VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength) - : QRunnable(), + : m_isValid(true), m_bestResult(VBestSquare(data.gContour.GetSize(), saveLength, data.isOriginPaperOrientationPortrait)), m_data(data), stop(stop), @@ -75,6 +81,11 @@ VPosition::VPosition(const VPositionData &data, std::atomic_bool *stop, bool sav //--------------------------------------------------------------------------------------------------------------------- void VPosition::run() { + if (not m_isValid) + { + return; + } + if (stop->load()) { return; @@ -82,7 +93,21 @@ void VPosition::run() try { - FindBestPosition(); + for (int i=1; i<= m_data.detail.LayoutEdgesCount(); ++i) + { + if (stop->load()) + { + return; + } + + m_data.i = i; + FindBestPosition(); + + if (stop->load()) + { + return; + } + } } catch (const VException &e) { @@ -125,33 +150,33 @@ VBestSquare VPosition::ArrangeDetail(const VPositionData &data, std::atomic_bool return bestResult;//Not enough edges } - QScopedPointer thread_pool(new QThreadPool()); - QVector threads; - - auto Cleanup = qScopeGuard([&threads] - { - Q_ASSERT(not threads.isEmpty()); - qDeleteAll(threads.begin(), threads.end()); - }); + QFutureWatcher watcher; + QVector jobs; + jobs.reserve(data.gContour.GlobalEdgesCount()); for (int j=1; j <= data.gContour.GlobalEdgesCount(); ++j) { - QCoreApplication::processEvents(); + VPositionData linkedData = data; + linkedData.j = j; - for (int i=1; i<= detailEdgesCount; ++i) - { - VPositionData linkedData = data; - linkedData.i = i; - linkedData.j = j; - - auto *thread = new VPosition(linkedData, stop, saveLength); - thread->setAutoDelete(false); - threads.append(thread); - thread_pool->start(thread); - } + jobs.append(VPosition(linkedData, stop, saveLength)); } - Q_ASSERT(not threads.isEmpty()); + Q_ASSERT(not jobs.isEmpty()); + + std::function Nest = [](VPosition position) + { + position.run(); + return position.getBestResult(); + }; + + watcher.setFuture(QtConcurrent::mapped(jobs, Nest)); + + while(not watcher.isStarted()) + { + QCoreApplication::processEvents(); + QThread::msleep(250); + } // Wait for done do @@ -159,16 +184,24 @@ VBestSquare VPosition::ArrangeDetail(const VPositionData &data, std::atomic_bool QCoreApplication::processEvents(); QThread::msleep(250); } - while(thread_pool->activeThreadCount() > 0 && not stop->load()); + while(watcher.isRunning() && not stop->load()); if (stop->load()) { + do + { + QCoreApplication::processEvents(); + QThread::msleep(250); + } + while(watcher.isRunning()); + return bestResult; } - for (auto &thread : threads) + QList results = watcher.future().results(); + for (auto &result : results) { - bestResult.NewResult(thread->getBestResult()); + bestResult.NewResult(result); } return bestResult; @@ -427,6 +460,11 @@ void VPosition::FollowGrainline() detailGrainline = workDetail.GetMatrix().map(detailGrainline); } + if (stop->load()) + { + return; + } + const qreal angle = detailGrainline.angleTo(FabricGrainline()); if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth || @@ -435,6 +473,11 @@ void VPosition::FollowGrainline() RotateOnAngle(angle); } + if (stop->load()) + { + return; + } + if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth || m_data.detail.GrainlineArrowType() == ArrowType::atRear) { @@ -456,6 +499,11 @@ void VPosition::FindBestPosition() SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine); } + if (stop->load()) + { + return; + } + if (m_data.rotate) { Rotate(m_data.rotationNumber); diff --git a/src/libs/vlayout/vposition.h b/src/libs/vlayout/vposition.h index 0daa7442e..b089ad62f 100644 --- a/src/libs/vlayout/vposition.h +++ b/src/libs/vlayout/vposition.h @@ -53,27 +53,28 @@ struct VPositionData bool isOriginPaperOrientationPortrait{true}; }; -class VPosition : public QRunnable +class VPosition { public: + VPosition(); VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength); - virtual ~VPosition() override = default; + virtual ~VPosition()= default; - virtual void run() override; + virtual void run(); VBestSquare getBestResult() const; static VBestSquare ArrangeDetail(const VPositionData &data, std::atomic_bool *stop, bool saveLength); private: - Q_DISABLE_COPY(VPosition) - VBestSquare m_bestResult; - VPositionData m_data; - std::atomic_bool *stop; + bool m_isValid{false}; + VBestSquare m_bestResult{}; + VPositionData m_data{}; + std::atomic_bool *stop{nullptr}; /** * @brief angle_between keep angle between global edge and detail edge. Need for optimization rotation. */ - qreal angle_between; + qreal angle_between{0}; enum class CrossingType : char {