create stopable job which could be repeatedly run
This commit is contained in:
parent
43d200a7fb
commit
205f8cf86d
@ -13,9 +13,10 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace GUI;
|
using namespace GUI;
|
||||||
|
|
||||||
|
|
||||||
namespace Priv {
|
namespace Priv {
|
||||||
|
|
||||||
static void process(std::unique_ptr<EmbossData> input);
|
static void process(std::unique_ptr<EmbossData> input, StopCondition is_stop);
|
||||||
static void finalize(const EmbossData &input, const indexed_triangle_set &result);
|
static void finalize(const EmbossData &input, const indexed_triangle_set &result);
|
||||||
|
|
||||||
// TODO: move to objec list utils
|
// TODO: move to objec list utils
|
||||||
@ -23,10 +24,9 @@ static void select_volume(ModelVolume *volume);
|
|||||||
|
|
||||||
} // namespace Priv
|
} // namespace Priv
|
||||||
|
|
||||||
EmbossJob::EmbossJob() : ReRunJob<EmbossData>(Priv::process) {}
|
EmbossJob::EmbossJob() : StopableJob<EmbossData>(Priv::process) {}
|
||||||
|
|
||||||
|
void Priv::process(std::unique_ptr<EmbossData> input, StopCondition is_stop)
|
||||||
void Priv::process(std::unique_ptr<EmbossData> input)
|
|
||||||
{
|
{
|
||||||
// only for sure
|
// only for sure
|
||||||
assert(input != nullptr);
|
assert(input != nullptr);
|
||||||
@ -34,14 +34,16 @@ void Priv::process(std::unique_ptr<EmbossData> input)
|
|||||||
// check if exist valid font
|
// check if exist valid font
|
||||||
if (input->font == nullptr) return;
|
if (input->font == nullptr) return;
|
||||||
|
|
||||||
// Do NOT process empty string
|
|
||||||
const TextConfiguration &cfg = input->text_configuration;
|
const TextConfiguration &cfg = input->text_configuration;
|
||||||
const std::string & text = cfg.text;
|
const std::string & text = cfg.text;
|
||||||
|
// Do NOT process empty string
|
||||||
if (text.empty()) return;
|
if (text.empty()) return;
|
||||||
|
|
||||||
const FontProp &prop = cfg.font_prop;
|
const FontProp &prop = cfg.font_prop;
|
||||||
ExPolygons shapes = Emboss::text2shapes(*input->font, text.c_str(), prop);
|
ExPolygons shapes = Emboss::text2shapes(*input->font, text.c_str(), prop);
|
||||||
|
|
||||||
|
if (is_stop()) return;
|
||||||
|
|
||||||
// exist 2d shape made by text ?
|
// exist 2d shape made by text ?
|
||||||
// (no shape means that font hasn't any of text symbols)
|
// (no shape means that font hasn't any of text symbols)
|
||||||
if (shapes.empty()) return;
|
if (shapes.empty()) return;
|
||||||
@ -49,7 +51,9 @@ void Priv::process(std::unique_ptr<EmbossData> input)
|
|||||||
float scale = prop.size_in_mm / input->font->ascent;
|
float scale = prop.size_in_mm / input->font->ascent;
|
||||||
auto projectZ = std::make_unique<Emboss::ProjectZ>(prop.emboss / scale);
|
auto projectZ = std::make_unique<Emboss::ProjectZ>(prop.emboss / scale);
|
||||||
Emboss::ProjectScale project(std::move(projectZ), scale);
|
Emboss::ProjectScale project(std::move(projectZ), scale);
|
||||||
auto its = std::make_unique<indexed_triangle_set>(Emboss::polygons2model(shapes, project));
|
auto its = std::make_unique<indexed_triangle_set>(Emboss::polygons2model(shapes, project));
|
||||||
|
|
||||||
|
if (is_stop()) return;
|
||||||
|
|
||||||
// for sure that some object is created from shape
|
// for sure that some object is created from shape
|
||||||
if (its->indices.empty()) return;
|
if (its->indices.empty()) return;
|
||||||
@ -72,9 +76,11 @@ void Priv::process(std::unique_ptr<EmbossData> input)
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
Data *data = new Data(std::move(input), std::move(its));
|
Data *data = new Data(std::move(input), std::move(its));
|
||||||
|
// How to proof that call, will be done on exit?
|
||||||
wxGetApp().plater()->CallAfter([data]() {
|
wxGetApp().plater()->CallAfter([data]() {
|
||||||
Priv::finalize(*data->input, *data->result);
|
// because of finalize exception delete must be in ScopeGuard
|
||||||
delete data;
|
ScopeGuard sg([data]() { delete data; });
|
||||||
|
Priv::finalize(*data->input, *data->result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ namespace Slic3r::GUI {
|
|||||||
// inspired by Job.hpp
|
// inspired by Job.hpp
|
||||||
// All public function can be call only from UI thread
|
// All public function can be call only from UI thread
|
||||||
// Mechanism to stack processing and do only last one
|
// Mechanism to stack processing and do only last one
|
||||||
template<typename TIn> class ReRunJob
|
template<typename TIn>
|
||||||
|
class ReRunJob
|
||||||
{
|
{
|
||||||
std::mutex m_next_mutex;
|
std::mutex m_next_mutex;
|
||||||
std::unique_ptr<TIn> m_input_next = nullptr;
|
std::unique_ptr<TIn> m_input_next = nullptr;
|
||||||
@ -77,6 +78,91 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using StopCondition = std::function<bool(void)>;
|
||||||
|
// add stop ability
|
||||||
|
template<typename TIn> class StopableJob
|
||||||
|
{
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::unique_ptr<TIn> m_input_next = nullptr;
|
||||||
|
|
||||||
|
std::thread m_thread;
|
||||||
|
// indicate checking of new input.
|
||||||
|
bool m_running = false;
|
||||||
|
bool m_stop = false;
|
||||||
|
|
||||||
|
|
||||||
|
using Func = std::function<void(std::unique_ptr<TIn>, StopCondition)>;
|
||||||
|
Func m_func;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StopableJob(Func func) : m_func(func) {}
|
||||||
|
virtual ~StopableJob() {
|
||||||
|
stop();
|
||||||
|
join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void re_run(std::unique_ptr<TIn> input)
|
||||||
|
{
|
||||||
|
if (input == nullptr) return;
|
||||||
|
{
|
||||||
|
// keep access to next input
|
||||||
|
std::lock_guard lg(m_mutex);
|
||||||
|
if (m_running) {
|
||||||
|
// when runnig
|
||||||
|
m_stop = true;
|
||||||
|
m_input_next = std::move(input);
|
||||||
|
return; // on end of run will be used new input
|
||||||
|
}
|
||||||
|
m_running = true;
|
||||||
|
m_stop = false;
|
||||||
|
}
|
||||||
|
if (m_thread.joinable()) m_thread.join();
|
||||||
|
// at this moment is not running --> stoped
|
||||||
|
assert(m_input_next == nullptr);
|
||||||
|
try { // Execute the job
|
||||||
|
m_thread = std::thread(
|
||||||
|
[this](std::unique_ptr<TIn> input) {
|
||||||
|
do {
|
||||||
|
m_func(std::move(input), [this]() { return is_stoping(); });
|
||||||
|
|
||||||
|
std::lock_guard lg(m_mutex);
|
||||||
|
m_stop = false;
|
||||||
|
// this is not while (end)condition because of lock guard
|
||||||
|
if (m_input_next == nullptr) {
|
||||||
|
m_running = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input = std::move(m_input_next);
|
||||||
|
m_input_next = nullptr;
|
||||||
|
} while (true);
|
||||||
|
},
|
||||||
|
std::move(input));
|
||||||
|
} catch (std::exception &) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_running()
|
||||||
|
{
|
||||||
|
std::lock_guard lg(m_mutex);
|
||||||
|
return m_running;
|
||||||
|
}
|
||||||
|
bool is_stoping()
|
||||||
|
{
|
||||||
|
std::lock_guard lg(m_mutex);
|
||||||
|
return m_stop;
|
||||||
|
}
|
||||||
|
void stop() {
|
||||||
|
std::lock_guard lg(m_mutex);
|
||||||
|
m_input_next = nullptr;
|
||||||
|
m_stop = true;
|
||||||
|
}
|
||||||
|
// blocking until stop,
|
||||||
|
void join(int timeout_ms = 0)
|
||||||
|
{
|
||||||
|
if (m_thread.joinable()) m_thread.join();
|
||||||
|
assert(!m_running);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct EmbossData
|
struct EmbossData
|
||||||
{
|
{
|
||||||
// Pointer on Data of font (glyph shapes)
|
// Pointer on Data of font (glyph shapes)
|
||||||
@ -91,7 +177,7 @@ struct EmbossData
|
|||||||
int object_idx;
|
int object_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmbossJob : public ReRunJob<EmbossData>
|
class EmbossJob : public StopableJob<EmbossData>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EmbossJob();
|
EmbossJob();
|
||||||
|
Loading…
Reference in New Issue
Block a user