mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 10:06:02 +08:00
Create Stopable job
This commit is contained in:
parent
205f8cf86d
commit
bba9dab8c8
@ -208,7 +208,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLGizmoEmboss::~GLGizmoEmboss() {}
|
GLGizmoEmboss::~GLGizmoEmboss() { m_job->stop(); }
|
||||||
|
|
||||||
void GLGizmoEmboss::set_fine_position()
|
void GLGizmoEmboss::set_fine_position()
|
||||||
{
|
{
|
||||||
@ -333,6 +333,8 @@ void GLGizmoEmboss::on_set_state()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_volume = nullptr;
|
m_volume = nullptr;
|
||||||
|
m_job->stop();
|
||||||
|
m_job->join(); // free thread resource
|
||||||
remove_notification_not_valid_font();
|
remove_notification_not_valid_font();
|
||||||
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
|
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
|
||||||
if (!m_is_initialized) initialize();
|
if (!m_is_initialized) initialize();
|
||||||
@ -478,7 +480,7 @@ bool GLGizmoEmboss::process()
|
|||||||
data->volume_name = create_volume_name();
|
data->volume_name = create_volume_name();
|
||||||
data->volume_ptr = m_volume;
|
data->volume_ptr = m_volume;
|
||||||
data->object_idx = m_parent.get_selection().get_object_idx();
|
data->object_idx = m_parent.get_selection().get_object_idx();
|
||||||
m_job->re_run(std::move(data));
|
m_job->run(std::move(data));
|
||||||
|
|
||||||
// notification is removed befor object is changed by job
|
// notification is removed befor object is changed by job
|
||||||
remove_notification_not_valid_font();
|
remove_notification_not_valid_font();
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace GUI;
|
using namespace GUI;
|
||||||
|
|
||||||
|
|
||||||
namespace Priv {
|
namespace Priv {
|
||||||
|
|
||||||
static void process(std::unique_ptr<EmbossData> input, StopCondition is_stop);
|
static void process(std::unique_ptr<EmbossData> input, StopCondition is_stop);
|
||||||
@ -28,6 +27,10 @@ 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, StopCondition is_stop)
|
||||||
{
|
{
|
||||||
|
// Changing cursor to busy
|
||||||
|
wxBeginBusyCursor();
|
||||||
|
ScopeGuard sg([]() { wxEndBusyCursor(); });
|
||||||
|
|
||||||
// only for sure
|
// only for sure
|
||||||
assert(input != nullptr);
|
assert(input != nullptr);
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
#ifndef slic3r_EmbossJob_hpp_
|
#ifndef slic3r_EmbossJob_hpp_
|
||||||
#define slic3r_EmbossJob_hpp_
|
#define slic3r_EmbossJob_hpp_
|
||||||
|
|
||||||
#include <memory>
|
#include "StopableJob.hpp"
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include "Job.hpp"
|
|
||||||
|
|
||||||
#include "libslic3r/Emboss.hpp"
|
#include "libslic3r/Emboss.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -14,155 +10,6 @@ class ModelVolume;
|
|||||||
|
|
||||||
namespace Slic3r::GUI {
|
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
|
|
||||||
{
|
|
||||||
std::mutex m_next_mutex;
|
|
||||||
std::unique_ptr<TIn> m_input_next = nullptr;
|
|
||||||
|
|
||||||
std::thread m_thread;
|
|
||||||
// indicate checking of new input.
|
|
||||||
std::atomic<bool> m_running{false};
|
|
||||||
|
|
||||||
using Func = std::function<void(std::unique_ptr<TIn>)>;
|
|
||||||
Func m_func;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ReRunJob(Func func) : m_func(func) {}
|
|
||||||
virtual ~ReRunJob() { join(); }
|
|
||||||
|
|
||||||
void re_run(std::unique_ptr<TIn> input)
|
|
||||||
{
|
|
||||||
if (input == nullptr) return;
|
|
||||||
{
|
|
||||||
// keep access to next input
|
|
||||||
std::lock_guard lg(m_next_mutex);
|
|
||||||
if (is_running()) {
|
|
||||||
// when runnig
|
|
||||||
m_input_next = std::move(input);
|
|
||||||
return; // on end of run will be used new input
|
|
||||||
}
|
|
||||||
m_running.store(true);
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
|
|
||||||
std::lock_guard lg(m_next_mutex);
|
|
||||||
// it is not in while condition because of lock guard
|
|
||||||
if (m_input_next == nullptr) {
|
|
||||||
m_running.store(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
input = std::move(m_input_next);
|
|
||||||
m_input_next = nullptr;
|
|
||||||
} while (true);
|
|
||||||
},
|
|
||||||
std::move(input));
|
|
||||||
} catch (std::exception &) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_running() const { return m_running.load(); }
|
|
||||||
void join()
|
|
||||||
{
|
|
||||||
if (m_thread.joinable()) m_thread.join();
|
|
||||||
assert(!is_running());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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)
|
||||||
|
83
src/slic3r/GUI/Jobs/ReRunJob.hpp
Normal file
83
src/slic3r/GUI/Jobs/ReRunJob.hpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#ifndef slic3r_ReRunJob_hpp_
|
||||||
|
#define slic3r_ReRunJob_hpp_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace Slic3r::GUI {
|
||||||
|
|
||||||
|
// inspired by Job.hpp
|
||||||
|
// All public function can be call only from UI thread
|
||||||
|
// Mechanism to stack processing unique input and do only the last one
|
||||||
|
template<typename TIn>
|
||||||
|
class ReRunJob
|
||||||
|
{
|
||||||
|
std::mutex m_next_mutex;
|
||||||
|
std::unique_ptr<TIn> m_input_next = nullptr;
|
||||||
|
|
||||||
|
std::thread m_thread;
|
||||||
|
// indicate checking of new input.
|
||||||
|
std::atomic<bool> m_running{false};
|
||||||
|
|
||||||
|
using Func = std::function<void(std::unique_ptr<TIn>)>;
|
||||||
|
Func m_func;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReRunJob(Func func) : m_func(func) {}
|
||||||
|
virtual ~ReRunJob() {
|
||||||
|
try {
|
||||||
|
// thread join could throw exception
|
||||||
|
// https://en.cppreference.com/w/cpp/thread/thread/join
|
||||||
|
join();
|
||||||
|
} catch (std::system_error err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void re_run(std::unique_ptr<TIn> input)
|
||||||
|
{
|
||||||
|
if (input == nullptr) return;
|
||||||
|
{
|
||||||
|
// keep access to next input
|
||||||
|
std::lock_guard lg(m_next_mutex);
|
||||||
|
if (is_running()) {
|
||||||
|
// when runnig
|
||||||
|
m_input_next = std::move(input);
|
||||||
|
return; // on end of run will be used new input
|
||||||
|
}
|
||||||
|
m_running.store(true);
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
|
||||||
|
std::lock_guard lg(m_next_mutex);
|
||||||
|
// it is not in while condition because of lock guard
|
||||||
|
if (m_input_next == nullptr) {
|
||||||
|
m_running.store(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input = std::move(m_input_next);
|
||||||
|
m_input_next = nullptr;
|
||||||
|
} while (true);
|
||||||
|
},
|
||||||
|
std::move(input));
|
||||||
|
} catch (std::exception &) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_running() const { return m_running.load(); }
|
||||||
|
void join()
|
||||||
|
{
|
||||||
|
if (m_thread.joinable()) m_thread.join();
|
||||||
|
assert(!is_running());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // slic3r_ReRunJob_hpp_
|
106
src/slic3r/GUI/Jobs/StopableJob.hpp
Normal file
106
src/slic3r/GUI/Jobs/StopableJob.hpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#ifndef slic3r_StopableJob_hpp_
|
||||||
|
#define slic3r_StopableJob_hpp_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
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
|
||||||
|
// Ability to stop processing developer must add check into m_func
|
||||||
|
using StopCondition = std::function<bool(void)>;
|
||||||
|
template<typename TIn> class StopableJob
|
||||||
|
{
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::unique_ptr<TIn> m_input_next = nullptr;
|
||||||
|
|
||||||
|
std::thread m_thread;
|
||||||
|
// when running == true, than check of new input in thread.
|
||||||
|
bool m_running = false;
|
||||||
|
// faster interupt inside func, developer must add StopCondifion call
|
||||||
|
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();
|
||||||
|
try {
|
||||||
|
// thread join could throw exception
|
||||||
|
// https://en.cppreference.com/w/cpp/thread/thread/join
|
||||||
|
join();
|
||||||
|
} catch (std::system_error err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void 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);
|
||||||
|
if (!m_running) return;
|
||||||
|
m_input_next = nullptr;
|
||||||
|
m_stop = true;
|
||||||
|
}
|
||||||
|
// Be Carefull, blocking until join
|
||||||
|
// call stop when you not sure
|
||||||
|
void join(int timeout_ms = 0)
|
||||||
|
{
|
||||||
|
if (m_thread.joinable()) m_thread.join();
|
||||||
|
assert(!m_running);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif // slic3r_StopableJob_hpp_
|
Loading…
x
Reference in New Issue
Block a user