WIP: Fixed some issues with cancelation & restart of background processing.
This commit is contained in:
parent
6ae1517e13
commit
f2b0904d12
@ -837,6 +837,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||||||
enum Status {
|
enum Status {
|
||||||
Unknown,
|
Unknown,
|
||||||
Deleted,
|
Deleted,
|
||||||
|
Reused,
|
||||||
New
|
New
|
||||||
};
|
};
|
||||||
PrintObjectStatus(PrintObject *print_object, Status status = Unknown) :
|
PrintObjectStatus(PrintObject *print_object, Status status = Unknown) :
|
||||||
@ -931,6 +932,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||||||
{
|
{
|
||||||
std::vector<PrintObject*> print_objects_new;
|
std::vector<PrintObject*> print_objects_new;
|
||||||
print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size()));
|
print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size()));
|
||||||
|
bool new_objects = false;
|
||||||
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
||||||
for (ModelObject *model_object : m_model.objects) {
|
for (ModelObject *model_object : m_model.objects) {
|
||||||
auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id()));
|
auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id()));
|
||||||
@ -953,7 +955,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||||||
print_object->set_copies(print_instances.copies);
|
print_object->set_copies(print_instances.copies);
|
||||||
print_object->config_apply(config);
|
print_object->config_apply(config);
|
||||||
print_objects_new.emplace_back(print_object);
|
print_objects_new.emplace_back(print_object);
|
||||||
print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
// print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
||||||
|
new_objects = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -971,7 +974,10 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||||||
print_object->set_copies(new_instances.copies);
|
print_object->set_copies(new_instances.copies);
|
||||||
print_object->config_apply(config);
|
print_object->config_apply(config);
|
||||||
print_objects_new.emplace_back(print_object);
|
print_objects_new.emplace_back(print_object);
|
||||||
print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
// print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
||||||
|
new_objects = true;
|
||||||
|
if (it_old != old.end())
|
||||||
|
const_cast<PrintObjectStatus*>(*it_old)->status = PrintObjectStatus::Deleted;
|
||||||
} else if ((*it_old)->print_object->copies() != new_instances.copies) {
|
} else if ((*it_old)->print_object->copies() != new_instances.copies) {
|
||||||
// The PrintObject already exists and the copies differ.
|
// The PrintObject already exists and the copies differ.
|
||||||
if ((*it_old)->print_object->copies().size() != new_instances.copies.size())
|
if ((*it_old)->print_object->copies().size() != new_instances.copies.size())
|
||||||
@ -979,14 +985,26 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
|||||||
update_apply_status(this->invalidate_step(psSkirt) || this->invalidate_step(psBrim) || this->invalidate_step(psGCodeExport));
|
update_apply_status(this->invalidate_step(psSkirt) || this->invalidate_step(psBrim) || this->invalidate_step(psGCodeExport));
|
||||||
(*it_old)->print_object->set_copies(new_instances.copies);
|
(*it_old)->print_object->set_copies(new_instances.copies);
|
||||||
print_objects_new.emplace_back((*it_old)->print_object);
|
print_objects_new.emplace_back((*it_old)->print_object);
|
||||||
|
const_cast<PrintObjectStatus*>(*it_old)->status = PrintObjectStatus::Reused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_objects != print_objects_new) {
|
if (m_objects != print_objects_new) {
|
||||||
m_cancel_callback();
|
m_cancel_callback();
|
||||||
m_objects = print_objects_new;
|
m_objects = print_objects_new;
|
||||||
update_apply_status(false);
|
// Delete the PrintObjects marked as Unknown or Deleted.
|
||||||
|
bool deleted_objects = false;
|
||||||
|
for (auto &pos : print_object_status)
|
||||||
|
if (pos.status == PrintObjectStatus::Unknown || pos.status == PrintObjectStatus::Deleted) {
|
||||||
|
// update_apply_status(pos.print_object->invalidate_all_steps());
|
||||||
|
delete pos.print_object;
|
||||||
|
deleted_objects = true;
|
||||||
|
}
|
||||||
|
if (deleted_objects)
|
||||||
|
update_apply_status(this->invalidate_step(psSkirt) || this->invalidate_step(psBrim) || this->invalidate_step(psWipeTower) || this->invalidate_step(psGCodeExport));
|
||||||
|
update_apply_status(new_objects);
|
||||||
}
|
}
|
||||||
|
print_object_status.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Synchronize configs of ModelVolumes, synchronize AMF / 3MF materials (and their configs), refresh PrintRegions.
|
// 5) Synchronize configs of ModelVolumes, synchronize AMF / 3MF materials (and their configs), refresh PrintRegions.
|
||||||
|
@ -485,11 +485,22 @@ public:
|
|||||||
// the state of the finished or running calculations.
|
// the state of the finished or running calculations.
|
||||||
void set_cancel_callback(cancel_callback_type cancel_callback) { m_cancel_callback = cancel_callback; }
|
void set_cancel_callback(cancel_callback_type cancel_callback) { m_cancel_callback = cancel_callback; }
|
||||||
// Has the calculation been canceled?
|
// Has the calculation been canceled?
|
||||||
bool canceled() const { return m_canceled; }
|
enum CancelStatus {
|
||||||
|
// No cancelation, background processing should run.
|
||||||
|
NOT_CANCELED = 0,
|
||||||
|
// Canceled by user from the user interface (user pressed the "Cancel" button or user closed the application).
|
||||||
|
CANCELED_BY_USER = 1,
|
||||||
|
// Canceled internally from Print::apply() through the Print/PrintObject::invalidate_step() or ::invalidate_all_steps().
|
||||||
|
CANCELED_INTERNAL = 2
|
||||||
|
};
|
||||||
|
CancelStatus cancel_status() const { return m_cancel_status; }
|
||||||
|
// Has the calculation been canceled?
|
||||||
|
bool canceled() const { return m_cancel_status; }
|
||||||
// Cancel the running computation. Stop execution of all the background threads.
|
// Cancel the running computation. Stop execution of all the background threads.
|
||||||
void cancel() { m_canceled = true; }
|
void cancel() { m_cancel_status = CANCELED_BY_USER; }
|
||||||
|
void cancel_internal() { m_cancel_status = CANCELED_INTERNAL; }
|
||||||
// Cancel the running computation. Stop execution of all the background threads.
|
// Cancel the running computation. Stop execution of all the background threads.
|
||||||
void restart() { m_canceled = false; }
|
void restart() { m_cancel_status = NOT_CANCELED; }
|
||||||
|
|
||||||
// Accessed by SupportMaterial
|
// Accessed by SupportMaterial
|
||||||
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
||||||
@ -513,7 +524,7 @@ private:
|
|||||||
|
|
||||||
// If the background processing stop was requested, throw CanceledException.
|
// If the background processing stop was requested, throw CanceledException.
|
||||||
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
|
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
|
||||||
void throw_if_canceled() const { if (m_canceled) throw CanceledException(); }
|
void throw_if_canceled() const { if (m_cancel_status) throw CanceledException(); }
|
||||||
|
|
||||||
void _make_skirt();
|
void _make_skirt();
|
||||||
void _make_brim();
|
void _make_brim();
|
||||||
@ -526,8 +537,7 @@ private:
|
|||||||
// while the data influencing the stage is modified.
|
// while the data influencing the stage is modified.
|
||||||
mutable tbb::mutex m_mutex;
|
mutable tbb::mutex m_mutex;
|
||||||
|
|
||||||
// Has the calculation been canceled?
|
tbb::atomic<CancelStatus> m_cancel_status;
|
||||||
tbb::atomic<bool> m_canceled;
|
|
||||||
// Callback to be evoked regularly to update state of the UI thread.
|
// Callback to be evoked regularly to update state of the UI thread.
|
||||||
status_callback_type m_status_callback;
|
status_callback_type m_status_callback;
|
||||||
|
|
||||||
|
@ -84,10 +84,14 @@ void BackgroundSlicingProcess::thread_proc()
|
|||||||
}
|
}
|
||||||
lck.lock();
|
lck.lock();
|
||||||
m_state = m_print->canceled() ? STATE_CANCELED : STATE_FINISHED;
|
m_state = m_print->canceled() ? STATE_CANCELED : STATE_FINISHED;
|
||||||
wxCommandEvent evt(m_event_finished_id);
|
if (m_print->cancel_status() != Print::CANCELED_INTERNAL) {
|
||||||
evt.SetString(error);
|
// Only post the canceled event, if canceled by user.
|
||||||
evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0));
|
// Don't post the canceled event, if canceled from Print::apply().
|
||||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
|
wxCommandEvent evt(m_event_finished_id);
|
||||||
|
evt.SetString(error);
|
||||||
|
evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0));
|
||||||
|
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
|
||||||
|
}
|
||||||
m_print->restart();
|
m_print->restart();
|
||||||
lck.unlock();
|
lck.unlock();
|
||||||
// Let the UI thread wake up if it is waiting for the background task to finish.
|
// Let the UI thread wake up if it is waiting for the background task to finish.
|
||||||
@ -134,7 +138,7 @@ bool BackgroundSlicingProcess::start()
|
|||||||
if (! this->idle())
|
if (! this->idle())
|
||||||
throw std::runtime_error("Cannot start a background task, the worker thread is not idle.");
|
throw std::runtime_error("Cannot start a background task, the worker thread is not idle.");
|
||||||
m_state = STATE_STARTED;
|
m_state = STATE_STARTED;
|
||||||
m_print->set_cancel_callback([this](){ this->stop(); });
|
m_print->set_cancel_callback([this](){ this->stop_internal(); });
|
||||||
lck.unlock();
|
lck.unlock();
|
||||||
m_condition.notify_one();
|
m_condition.notify_one();
|
||||||
return true;
|
return true;
|
||||||
@ -164,6 +168,23 @@ bool BackgroundSlicingProcess::stop()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To be called by Print::apply() through the Print::m_cancel_callback to stop the background
|
||||||
|
// processing before changing any data of running or finalized milestones.
|
||||||
|
// This function shall not trigger any UI update through the wxWidgets event.
|
||||||
|
void BackgroundSlicingProcess::stop_internal()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(m_mutex);
|
||||||
|
assert(m_state == STATE_STARTED || m_state == STATE_RUNNING || m_state == STATE_FINISHED || m_state == STATE_CANCELED);
|
||||||
|
if (m_state == STATE_STARTED || m_state == STATE_RUNNING) {
|
||||||
|
m_print->cancel_internal();
|
||||||
|
// Wait until the background processing stops by being canceled.
|
||||||
|
m_condition.wait(lck, [this](){ return m_state == STATE_CANCELED; });
|
||||||
|
}
|
||||||
|
// In the "Canceled" state. Reset the state to "Idle".
|
||||||
|
m_state = STATE_IDLE;
|
||||||
|
m_print->set_cancel_callback([](){});
|
||||||
|
}
|
||||||
|
|
||||||
// Apply config over the print. Returns false, if the new config values caused any of the already
|
// Apply config over the print. Returns false, if the new config values caused any of the already
|
||||||
// processed steps to be invalidated, therefore the task will need to be restarted.
|
// processed steps to be invalidated, therefore the task will need to be restarted.
|
||||||
bool BackgroundSlicingProcess::apply_config(const DynamicPrintConfig &config)
|
bool BackgroundSlicingProcess::apply_config(const DynamicPrintConfig &config)
|
||||||
|
@ -81,6 +81,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void thread_proc();
|
void thread_proc();
|
||||||
void join_background_thread();
|
void join_background_thread();
|
||||||
|
// To be called by Print::apply() through the Print::m_cancel_callback to stop the background
|
||||||
|
// processing before changing any data of running or finalized milestones.
|
||||||
|
// This function shall not trigger any UI update through the wxWidgets event.
|
||||||
|
void stop_internal();
|
||||||
|
|
||||||
Print *m_print = nullptr;
|
Print *m_print = nullptr;
|
||||||
// Data structure, to which the G-code export writes its annotations.
|
// Data structure, to which the G-code export writes its annotations.
|
||||||
|
Loading…
Reference in New Issue
Block a user