Suspend background processes while writing to shared data structures

This commit is contained in:
Alessandro Ranellucci 2014-06-13 23:27:52 +02:00
parent 6eec3440cc
commit 829bfeabe8
2 changed files with 35 additions and 2 deletions

View File

@ -19,6 +19,7 @@ my %prereqs = qw(
Scalar::Util 0 Scalar::Util 0
Test::Harness 0 Test::Harness 0
Test::More 0 Test::More 0
Thread::Semaphore 0
IO::Scalar 0 IO::Scalar 0
Time::HiRes 0 Time::HiRes 0
); );

View File

@ -7,6 +7,7 @@ use File::Basename qw(basename dirname);
use List::Util qw(sum first); use List::Util qw(sum first);
use Slic3r::Geometry qw(X Y Z MIN MAX scale unscale); use Slic3r::Geometry qw(X Y Z MIN MAX scale unscale);
use threads::shared qw(shared_clone); use threads::shared qw(shared_clone);
use Thread::Semaphore;
use Wx qw(:button :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc :panel :sizer :toolbar :window); use Wx qw(:button :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc :panel :sizer :toolbar :window);
use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_ACTIVATED use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_ACTIVATED
EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL
@ -39,10 +40,12 @@ our $PROCESS_COMPLETED_EVENT : shared = Wx::NewEventType;
use constant CANVAS_SIZE => [335,335]; use constant CANVAS_SIZE => [335,335];
use constant FILAMENT_CHOOSERS_SPACING => 3; use constant FILAMENT_CHOOSERS_SPACING => 3;
use constant PROCESS_DELAY => 1 * 1000; # milliseconds use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds
my $PreventListEvents = 0; my $PreventListEvents = 0;
my $sema = Thread::Semaphore->new;
sub new { sub new {
my $class = shift; my $class = shift;
my ($parent) = @_; my ($parent) = @_;
@ -566,6 +569,7 @@ sub rotate {
$model_object->update_bounding_box; $model_object->update_bounding_box;
# update print and start background processing # update print and start background processing
$self->suspend_background_process;
$self->{print}->add_model_object($model_object, $obj_idx); $self->{print}->add_model_object($model_object, $obj_idx);
$self->schedule_background_process; $self->schedule_background_process;
@ -602,6 +606,7 @@ sub changescale {
$model_object->update_bounding_box; $model_object->update_bounding_box;
# update print and start background processing # update print and start background processing
$self->suspend_background_process;
$self->{print}->add_model_object($model_object, $obj_idx); $self->{print}->add_model_object($model_object, $obj_idx);
$self->schedule_background_process; $self->schedule_background_process;
@ -648,6 +653,8 @@ sub split_object {
return; return;
} }
$self->suspend_background_process;
# create a bogus Model object, we only need to instantiate the new Model::Object objects # create a bogus Model object, we only need to instantiate the new Model::Object objects
my $new_model = Slic3r::Model->new; my $new_model = Slic3r::Model->new;
@ -700,7 +707,9 @@ sub schedule_background_process {
sub async_apply_config { sub async_apply_config {
my ($self) = @_; my ($self) = @_;
# TODO: pause process thread before applying new config # pause process thread before applying new config
# since we don't want to touch data that is being used by the threads
$self->suspend_background_process;
# apply new config # apply new config
my $invalidated = $self->{print}->apply_config($self->skeinpanel->config); my $invalidated = $self->{print}->apply_config($self->skeinpanel->config);
@ -721,6 +730,8 @@ sub async_apply_config {
sub start_background_process { sub start_background_process {
my ($self) = @_; my ($self) = @_;
$self->resume_background_process;
return if !$Slic3r::have_threads; return if !$Slic3r::have_threads;
return if !@{$self->{objects}}; return if !@{$self->{objects}};
return if $self->{process_thread}; return if $self->{process_thread};
@ -751,6 +762,10 @@ sub start_background_process {
Slic3r::thread_cleanup(); Slic3r::thread_cleanup();
threads->exit(); threads->exit();
}; };
local $SIG{'STOP'} = sub {
$sema->down;
$sema->up;
};
eval { eval {
$self->{print}->process; $self->{print}->process;
@ -790,6 +805,19 @@ sub stop_background_process {
} }
} }
sub suspend_background_process {
my ($self) = @_;
$sema->down;
$_->kill('STOP') for grep $_, $self->{process_thread}, $self->{export_thread};
}
sub resume_background_process {
my ($self) = @_;
$sema->up;
}
sub export_gcode { sub export_gcode {
my $self = shift; my $self = shift;
@ -885,6 +913,10 @@ sub on_process_completed {
Slic3r::thread_cleanup(); Slic3r::thread_cleanup();
threads->exit(); threads->exit();
}; };
local $SIG{'STOP'} = sub {
$sema->down;
$sema->up;
};
eval { eval {
$_thread_self->{print}->export_gcode(output_file => $_thread_self->{export_gcode_output_file}); $_thread_self->{print}->export_gcode(output_file => $_thread_self->{export_gcode_output_file});