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
This commit is contained in:
Roman Telezhynskyi 2019-08-22 10:57:38 +03:00
parent ab6413fb36
commit d930e94c42
5 changed files with 99 additions and 38 deletions

View File

@ -41,6 +41,11 @@ Q_DECL_CONSTEXPR inline qint64 Square(QSizeF size)
} }
} // anonymous namespace } // anonymous namespace
//---------------------------------------------------------------------------------------------------------------------
VBestSquare::VBestSquare()
: d(new VBestSquareData())
{}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VBestSquare::VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait) VBestSquare::VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait)
: d(new VBestSquareData(sheetSize, saveLength, isPortrait)) : d(new VBestSquareData(sheetSize, saveLength, isPortrait))
@ -111,7 +116,7 @@ void VBestSquare::NewResult(const VBestSquareResData &data)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VBestSquare::NewResult(const VBestSquare &best) 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()); NewResult(best.BestResultData());
} }

View File

@ -42,6 +42,7 @@ class VBestSquareData;
class VBestSquare class VBestSquare
{ {
public: public:
VBestSquare();
VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait); VBestSquare(QSizeF sheetSize, bool saveLength, bool isPortrait);
VBestSquare(const VBestSquare &res); VBestSquare(const VBestSquare &res);
virtual ~VBestSquare(); virtual ~VBestSquare();

View File

@ -42,8 +42,12 @@ QT_WARNING_DISABLE_GCC("-Wnon-virtual-dtor")
class VBestSquareData : public QSharedData class VBestSquareData : public QSharedData
{ {
public: public:
VBestSquareData()
{}
VBestSquareData(const QSizeF &sheetSize, bool saveLength, bool isPortrait) VBestSquareData(const QSizeF &sheetSize, bool saveLength, bool isPortrait)
: sheetSize(sheetSize), : isValid(true),
sheetSize(sheetSize),
saveLength(saveLength), saveLength(saveLength),
isPortrait(isPortrait) isPortrait(isPortrait)
{ {
@ -52,6 +56,7 @@ public:
VBestSquareData(const VBestSquareData &res) VBestSquareData(const VBestSquareData &res)
: QSharedData(res), : QSharedData(res),
isValid(res.isValid),
sheetSize(res.sheetSize), sheetSize(res.sheetSize),
valideResult(res.valideResult), valideResult(res.valideResult),
saveLength(res.saveLength), saveLength(res.saveLength),
@ -63,9 +68,10 @@ public:
~VBestSquareData() {} ~VBestSquareData() {}
QSizeF sheetSize; bool isValid{false};
QSizeF sheetSize{};
bool valideResult{false}; bool valideResult{false};
bool saveLength; bool saveLength{false};
VBestSquareResData data{}; VBestSquareResData data{};
bool isPortrait{true}; bool isPortrait{true};
bool terminatedByException{false}; bool terminatedByException{false};

View File

@ -29,6 +29,8 @@
#include "vposition.h" #include "vposition.h"
#include <QDir> #include <QDir>
#include <QtConcurrent>
#include <QFutureWatcher>
#include <QImage> #include <QImage>
#include <QLineF> #include <QLineF>
#include <QPainter> #include <QPainter>
@ -58,9 +60,13 @@
#include <QScopeGuard> #include <QScopeGuard>
#endif #endif
//---------------------------------------------------------------------------------------------------------------------
VPosition::VPosition()
{}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPosition::VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength) 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_bestResult(VBestSquare(data.gContour.GetSize(), saveLength, data.isOriginPaperOrientationPortrait)),
m_data(data), m_data(data),
stop(stop), stop(stop),
@ -75,6 +81,11 @@ VPosition::VPosition(const VPositionData &data, std::atomic_bool *stop, bool sav
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPosition::run() void VPosition::run()
{ {
if (not m_isValid)
{
return;
}
if (stop->load()) if (stop->load())
{ {
return; return;
@ -82,7 +93,21 @@ void VPosition::run()
try 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) catch (const VException &e)
{ {
@ -125,33 +150,33 @@ VBestSquare VPosition::ArrangeDetail(const VPositionData &data, std::atomic_bool
return bestResult;//Not enough edges return bestResult;//Not enough edges
} }
QScopedPointer<QThreadPool> thread_pool(new QThreadPool()); QFutureWatcher<VBestSquare> watcher;
QVector<VPosition *> threads; QVector<VPosition> jobs;
jobs.reserve(data.gContour.GlobalEdgesCount());
auto Cleanup = qScopeGuard([&threads]
{
Q_ASSERT(not threads.isEmpty());
qDeleteAll(threads.begin(), threads.end());
});
for (int j=1; j <= data.gContour.GlobalEdgesCount(); ++j) for (int j=1; j <= data.gContour.GlobalEdgesCount(); ++j)
{ {
QCoreApplication::processEvents(); VPositionData linkedData = data;
linkedData.j = j;
for (int i=1; i<= detailEdgesCount; ++i) jobs.append(VPosition(linkedData, stop, saveLength));
{
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);
}
} }
Q_ASSERT(not threads.isEmpty()); Q_ASSERT(not jobs.isEmpty());
std::function<VBestSquare (VPosition position)> 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 // Wait for done
do do
@ -159,16 +184,24 @@ VBestSquare VPosition::ArrangeDetail(const VPositionData &data, std::atomic_bool
QCoreApplication::processEvents(); QCoreApplication::processEvents();
QThread::msleep(250); QThread::msleep(250);
} }
while(thread_pool->activeThreadCount() > 0 && not stop->load()); while(watcher.isRunning() && not stop->load());
if (stop->load()) if (stop->load())
{ {
do
{
QCoreApplication::processEvents();
QThread::msleep(250);
}
while(watcher.isRunning());
return bestResult; return bestResult;
} }
for (auto &thread : threads) QList<VBestSquare> results = watcher.future().results();
for (auto &result : results)
{ {
bestResult.NewResult(thread->getBestResult()); bestResult.NewResult(result);
} }
return bestResult; return bestResult;
@ -427,6 +460,11 @@ void VPosition::FollowGrainline()
detailGrainline = workDetail.GetMatrix().map(detailGrainline); detailGrainline = workDetail.GetMatrix().map(detailGrainline);
} }
if (stop->load())
{
return;
}
const qreal angle = detailGrainline.angleTo(FabricGrainline()); const qreal angle = detailGrainline.angleTo(FabricGrainline());
if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth || if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth ||
@ -435,6 +473,11 @@ void VPosition::FollowGrainline()
RotateOnAngle(angle); RotateOnAngle(angle);
} }
if (stop->load())
{
return;
}
if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth || if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth ||
m_data.detail.GrainlineArrowType() == ArrowType::atRear) m_data.detail.GrainlineArrowType() == ArrowType::atRear)
{ {
@ -456,6 +499,11 @@ void VPosition::FindBestPosition()
SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine); SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine);
} }
if (stop->load())
{
return;
}
if (m_data.rotate) if (m_data.rotate)
{ {
Rotate(m_data.rotationNumber); Rotate(m_data.rotationNumber);

View File

@ -53,27 +53,28 @@ struct VPositionData
bool isOriginPaperOrientationPortrait{true}; bool isOriginPaperOrientationPortrait{true};
}; };
class VPosition : public QRunnable class VPosition
{ {
public: public:
VPosition();
VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength); 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; VBestSquare getBestResult() const;
static VBestSquare ArrangeDetail(const VPositionData &data, std::atomic_bool *stop, bool saveLength); static VBestSquare ArrangeDetail(const VPositionData &data, std::atomic_bool *stop, bool saveLength);
private: private:
Q_DISABLE_COPY(VPosition) bool m_isValid{false};
VBestSquare m_bestResult; VBestSquare m_bestResult{};
VPositionData m_data; VPositionData m_data{};
std::atomic_bool *stop; std::atomic_bool *stop{nullptr};
/** /**
* @brief angle_between keep angle between global edge and detail edge. Need for optimization rotation. * @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 enum class CrossingType : char
{ {