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
//---------------------------------------------------------------------------------------------------------------------
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());
}

View File

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

View File

@ -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};

View File

@ -29,6 +29,8 @@
#include "vposition.h"
#include <QDir>
#include <QtConcurrent>
#include <QFutureWatcher>
#include <QImage>
#include <QLineF>
#include <QPainter>
@ -58,9 +60,13 @@
#include <QScopeGuard>
#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<QThreadPool> thread_pool(new QThreadPool());
QVector<VPosition *> threads;
auto Cleanup = qScopeGuard([&threads]
{
Q_ASSERT(not threads.isEmpty());
qDeleteAll(threads.begin(), threads.end());
});
QFutureWatcher<VBestSquare> watcher;
QVector<VPosition> 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<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
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<VBestSquare> 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);

View File

@ -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
{