Some comments and avoid race condition with background process.
This commit is contained in:
parent
696ade15ca
commit
170789a787
1 changed files with 41 additions and 4 deletions
|
@ -1222,11 +1222,22 @@ struct Plater::priv
|
||||||
|
|
||||||
BackgroundSlicingProcess background_process;
|
BackgroundSlicingProcess background_process;
|
||||||
|
|
||||||
|
// A class to handle UI jobs like arranging and optimizing rotation.
|
||||||
|
// These are not instant jobs, the user has to be informed about their
|
||||||
|
// state in the status progress indicator. On the other hand they are
|
||||||
|
// separated from the background slicing process. Ideally, these jobs should
|
||||||
|
// run when the background process is not running.
|
||||||
|
//
|
||||||
|
// TODO: A mechanism would be useful for blocking the plater interactions:
|
||||||
|
// objects would be frozen for the user. In case of arrange, an animation
|
||||||
|
// could be shown, or with the optimize orientations, partial results
|
||||||
|
// could be displayed.
|
||||||
class Job: public wxEvtHandler {
|
class Job: public wxEvtHandler {
|
||||||
int m_range = 100;
|
int m_range = 100;
|
||||||
std::future<void> m_ftr;
|
std::future<void> m_ftr;
|
||||||
priv *m_plater = nullptr;
|
priv *m_plater = nullptr;
|
||||||
std::atomic<bool> m_running {false}, m_canceled {false};
|
std::atomic<bool> m_running {false}, m_canceled {false};
|
||||||
|
bool m_stop_slicing = false;
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
m_running.store(true); process(); m_running.store(false);
|
m_running.store(true); process(); m_running.store(false);
|
||||||
|
@ -1240,6 +1251,7 @@ struct Plater::priv
|
||||||
// status range for a particular job
|
// status range for a particular job
|
||||||
virtual int status_range() const { return 100; }
|
virtual int status_range() const { return 100; }
|
||||||
|
|
||||||
|
// status update, to be used from the work thread (process() method)
|
||||||
void update_status(int st, const wxString& msg = "") {
|
void update_status(int st, const wxString& msg = "") {
|
||||||
auto evt = new wxThreadEvent(); evt->SetInt(st); evt->SetString(msg);
|
auto evt = new wxThreadEvent(); evt->SetInt(st); evt->SetString(msg);
|
||||||
wxQueueEvent(this, evt);
|
wxQueueEvent(this, evt);
|
||||||
|
@ -1250,7 +1262,9 @@ struct Plater::priv
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Job(priv *_plater): m_plater(_plater) {
|
Job(priv *_plater, bool stop_slicing = false):
|
||||||
|
m_plater(_plater), m_stop_slicing(stop_slicing)
|
||||||
|
{
|
||||||
Bind(wxEVT_THREAD, [this](const wxThreadEvent& evt){
|
Bind(wxEVT_THREAD, [this](const wxThreadEvent& evt){
|
||||||
auto msg = evt.GetString();
|
auto msg = evt.GetString();
|
||||||
if(! msg.empty()) plater().statusbar()->set_status_text(msg);
|
if(! msg.empty()) plater().statusbar()->set_status_text(msg);
|
||||||
|
@ -1278,19 +1292,39 @@ struct Plater::priv
|
||||||
|
|
||||||
virtual void process() = 0;
|
virtual void process() = 0;
|
||||||
|
|
||||||
void start() { // only if not running
|
void start() { // Start the job. No effect if the job is already running
|
||||||
if(! m_running.load()) {
|
if(! m_running.load()) {
|
||||||
|
|
||||||
|
if(m_stop_slicing) plater().background_process.stop();
|
||||||
|
|
||||||
|
// Save the current status indicatior range and push the new one
|
||||||
m_range = plater().statusbar()->get_range();
|
m_range = plater().statusbar()->get_range();
|
||||||
m_canceled.store(false);
|
|
||||||
plater().statusbar()->set_range(status_range());
|
plater().statusbar()->set_range(status_range());
|
||||||
|
|
||||||
|
// init cancellation flag and set the cancel callback
|
||||||
|
m_canceled.store(false);
|
||||||
plater().statusbar()->set_cancel_callback( [this](){
|
plater().statusbar()->set_cancel_callback( [this](){
|
||||||
m_canceled.store(true);
|
m_canceled.store(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Changing cursor to busy
|
||||||
wxBeginBusyCursor();
|
wxBeginBusyCursor();
|
||||||
m_ftr = std::async(std::launch::async, &Job::run, this);
|
|
||||||
|
try { // Execute the job
|
||||||
|
m_ftr = std::async(std::launch::async, &Job::run, this);
|
||||||
|
} catch(std::exception& ) {
|
||||||
|
update_status(status_range(),
|
||||||
|
_(L("ERROR: not enough resources to execute a new job.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The state changes will be undone when the process hits the
|
||||||
|
// last status value, in the status update handler (see ctor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To wait for the running job and join the threads. False is returned
|
||||||
|
// if the timeout has been reached and the job is still running. Call
|
||||||
|
// cancel() before this fn if you want to explicitly end the job.
|
||||||
bool join(int timeout_ms = 0) {
|
bool join(int timeout_ms = 0) {
|
||||||
if(!m_ftr.valid()) return true;
|
if(!m_ftr.valid()) return true;
|
||||||
|
|
||||||
|
@ -3676,6 +3710,9 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
|
||||||
|
|
||||||
void Plater::reslice()
|
void Plater::reslice()
|
||||||
{
|
{
|
||||||
|
// Stop arrange and (or) optimize rotation tasks.
|
||||||
|
this->stop_jobs();
|
||||||
|
|
||||||
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
|
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
|
||||||
// bitmask of UpdateBackgroundProcessReturnState
|
// bitmask of UpdateBackgroundProcessReturnState
|
||||||
unsigned int state = this->p->update_background_process(true);
|
unsigned int state = this->p->update_background_process(true);
|
||||||
|
|
Loading…
Add table
Reference in a new issue