create stopable job which could be repeatedly run
This commit is contained in:
parent
43d200a7fb
commit
205f8cf86d
2 changed files with 102 additions and 10 deletions
|
@ -13,9 +13,10 @@
|
|||
using namespace Slic3r;
|
||||
using namespace GUI;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
// TODO: move to objec list utils
|
||||
|
@ -23,10 +24,9 @@ static void select_volume(ModelVolume *volume);
|
|||
|
||||
} // namespace Priv
|
||||
|
||||
EmbossJob::EmbossJob() : ReRunJob<EmbossData>(Priv::process) {}
|
||||
EmbossJob::EmbossJob() : StopableJob<EmbossData>(Priv::process) {}
|
||||
|
||||
|
||||
void Priv::process(std::unique_ptr<EmbossData> input)
|
||||
void Priv::process(std::unique_ptr<EmbossData> input, StopCondition is_stop)
|
||||
{
|
||||
// only for sure
|
||||
assert(input != nullptr);
|
||||
|
@ -34,14 +34,16 @@ void Priv::process(std::unique_ptr<EmbossData> input)
|
|||
// check if exist valid font
|
||||
if (input->font == nullptr) return;
|
||||
|
||||
// Do NOT process empty string
|
||||
const TextConfiguration &cfg = input->text_configuration;
|
||||
const std::string & text = cfg.text;
|
||||
// Do NOT process empty string
|
||||
if (text.empty()) return;
|
||||
|
||||
const FontProp &prop = cfg.font_prop;
|
||||
ExPolygons shapes = Emboss::text2shapes(*input->font, text.c_str(), prop);
|
||||
|
||||
if (is_stop()) return;
|
||||
|
||||
// exist 2d shape made by text ?
|
||||
// (no shape means that font hasn't any of text symbols)
|
||||
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;
|
||||
auto projectZ = std::make_unique<Emboss::ProjectZ>(prop.emboss / 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
|
||||
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));
|
||||
// How to proof that call, will be done on exit?
|
||||
wxGetApp().plater()->CallAfter([data]() {
|
||||
Priv::finalize(*data->input, *data->result);
|
||||
delete data;
|
||||
// because of finalize exception delete must be in ScopeGuard
|
||||
ScopeGuard sg([data]() { delete data; });
|
||||
Priv::finalize(*data->input, *data->result);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ namespace Slic3r::GUI {
|
|||
// inspired by Job.hpp
|
||||
// All public function can be call only from UI thread
|
||||
// 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::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
|
||||
{
|
||||
// Pointer on Data of font (glyph shapes)
|
||||
|
@ -91,7 +177,7 @@ struct EmbossData
|
|||
int object_idx;
|
||||
};
|
||||
|
||||
class EmbossJob : public ReRunJob<EmbossData>
|
||||
class EmbossJob : public StopableJob<EmbossData>
|
||||
{
|
||||
public:
|
||||
EmbossJob();
|
||||
|
|
Loading…
Reference in a new issue