mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-24 07:03:59 -06:00
Work in progress: Good bye, Perl Threads!
This commit is contained in:
parent
86b79f89ad
commit
e931f75010
31 changed files with 833 additions and 1069 deletions
137
lib/Slic3r.pm
137
lib/Slic3r.pm
|
@ -1,5 +1,4 @@
|
|||
# This package loads all the non-GUI Slic3r perl packages.
|
||||
# In addition, it implements utility functions for file handling and threading.
|
||||
|
||||
package Slic3r;
|
||||
|
||||
|
@ -22,22 +21,11 @@ sub debugf {
|
|||
|
||||
our $loglevel = 0;
|
||||
|
||||
# load threads before Moo as required by it
|
||||
BEGIN {
|
||||
# Test, whether the perl was compiled with ithreads support and ithreads actually work.
|
||||
use Config;
|
||||
use Moo;
|
||||
my $have_threads = $Config{useithreads} && eval "use threads; use threads::shared; use Thread::Queue; 1";
|
||||
die "Slic3r Prusa Edition requires working Perl threads.\n" if ! $have_threads;
|
||||
die "threads.pm >= 1.96 is required, please update\n" if $threads::VERSION < 1.96;
|
||||
die "Perl threading is broken with this Moo version: " . $Moo::VERSION . "\n" if $Moo::VERSION == 1.003000;
|
||||
$debug = 1 if (defined($ENV{'SLIC3R_DEBUGOUT'}) && $ENV{'SLIC3R_DEBUGOUT'} == 1);
|
||||
print "Debugging output enabled\n" if $debug;
|
||||
}
|
||||
|
||||
warn "Running Slic3r under Perl 5.16 is neither supported nor recommended\n"
|
||||
if $^V == v5.16;
|
||||
|
||||
use FindBin;
|
||||
|
||||
# Let the XS module know where the GUI resources reside.
|
||||
|
@ -66,17 +54,11 @@ use Slic3r::Print::Object;
|
|||
use Slic3r::Print::Simple;
|
||||
use Slic3r::Surface;
|
||||
our $build = eval "use Slic3r::Build; 1";
|
||||
use Thread::Semaphore;
|
||||
|
||||
# Scaling between the float and integer coordinates.
|
||||
# Floats are in mm.
|
||||
use constant SCALING_FACTOR => 0.000001;
|
||||
|
||||
# Keep track of threads we created. Perl worker threads shall not create further threads.
|
||||
my @threads = ();
|
||||
my $pause_sema = Thread::Semaphore->new;
|
||||
my $paused = 0;
|
||||
|
||||
# Set the logging level at the Slic3r XS module.
|
||||
$Slic3r::loglevel = (defined($ENV{'SLIC3R_LOGLEVEL'}) && $ENV{'SLIC3R_LOGLEVEL'} =~ /^[1-9]/) ? $ENV{'SLIC3R_LOGLEVEL'} : 0;
|
||||
set_logging_level($Slic3r::loglevel);
|
||||
|
@ -85,121 +67,6 @@ set_logging_level($Slic3r::loglevel);
|
|||
# class instance in a thread safe manner.
|
||||
Slic3r::GCode::PlaceholderParser->new->evaluate_boolean_expression('1==1');
|
||||
|
||||
sub spawn_thread {
|
||||
my ($cb) = @_;
|
||||
@_ = ();
|
||||
my $thread = threads->create(sub {
|
||||
Slic3r::debugf "Starting thread %d...\n", threads->tid;
|
||||
local $SIG{'KILL'} = sub {
|
||||
Slic3r::debugf "Exiting thread %d...\n", threads->tid;
|
||||
Slic3r::thread_cleanup();
|
||||
threads->exit();
|
||||
};
|
||||
local $SIG{'STOP'} = sub {
|
||||
$pause_sema->down;
|
||||
$pause_sema->up;
|
||||
};
|
||||
$cb->();
|
||||
});
|
||||
push @threads, $thread->tid;
|
||||
return $thread;
|
||||
}
|
||||
|
||||
# call this at the very end of each thread (except the main one)
|
||||
# so that it does not try to free existing objects.
|
||||
# at that stage, existing objects are only those that we
|
||||
# inherited at the thread creation (thus shared) and those
|
||||
# that we are returning: destruction will be handled by the
|
||||
# main thread in both cases.
|
||||
# reminder: do not destroy inherited objects in other threads,
|
||||
# as the main thread will still try to destroy them when they
|
||||
# go out of scope; in other words, if you're undef()'ing an
|
||||
# object in a thread, make sure the main thread still holds a
|
||||
# reference so that it won't be destroyed in thread.
|
||||
sub thread_cleanup {
|
||||
# prevent destruction of shared objects
|
||||
no warnings 'redefine';
|
||||
*Slic3r::BridgeDetector::DESTROY = sub {};
|
||||
*Slic3r::Config::DESTROY = sub {};
|
||||
*Slic3r::Config::Full::DESTROY = sub {};
|
||||
*Slic3r::Config::GCode::DESTROY = sub {};
|
||||
*Slic3r::Config::Print::DESTROY = sub {};
|
||||
*Slic3r::Config::PrintObject::DESTROY = sub {};
|
||||
*Slic3r::Config::PrintRegion::DESTROY = sub {};
|
||||
*Slic3r::Config::Static::DESTROY = sub {};
|
||||
*Slic3r::ExPolygon::DESTROY = sub {};
|
||||
*Slic3r::ExPolygon::Collection::DESTROY = sub {};
|
||||
*Slic3r::ExtrusionLoop::DESTROY = sub {};
|
||||
*Slic3r::ExtrusionMultiPath::DESTROY = sub {};
|
||||
*Slic3r::ExtrusionPath::DESTROY = sub {};
|
||||
*Slic3r::ExtrusionPath::Collection::DESTROY = sub {};
|
||||
*Slic3r::ExtrusionSimulator::DESTROY = sub {};
|
||||
*Slic3r::Flow::DESTROY = sub {};
|
||||
*Slic3r::GCode::DESTROY = sub {};
|
||||
*Slic3r::GCode::PlaceholderParser::DESTROY = sub {};
|
||||
*Slic3r::GCode::PreviewData::DESTROY = sub {};
|
||||
*Slic3r::GCode::Sender::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBox::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBoxf::DESTROY = sub {};
|
||||
*Slic3r::Geometry::BoundingBoxf3::DESTROY = sub {};
|
||||
*Slic3r::Layer::PerimeterGenerator::DESTROY = sub {};
|
||||
*Slic3r::Line::DESTROY = sub {};
|
||||
*Slic3r::Linef3::DESTROY = sub {};
|
||||
*Slic3r::Model::DESTROY = sub {};
|
||||
*Slic3r::Model::Object::DESTROY = sub {};
|
||||
*Slic3r::Point::DESTROY = sub {};
|
||||
*Slic3r::Pointf::DESTROY = sub {};
|
||||
*Slic3r::Pointf3::DESTROY = sub {};
|
||||
*Slic3r::Polygon::DESTROY = sub {};
|
||||
*Slic3r::Polyline::DESTROY = sub {};
|
||||
*Slic3r::Polyline::Collection::DESTROY = sub {};
|
||||
*Slic3r::Print::DESTROY = sub {};
|
||||
*Slic3r::Print::Object::DESTROY = sub {};
|
||||
*Slic3r::Print::Region::DESTROY = sub {};
|
||||
*Slic3r::Surface::DESTROY = sub {};
|
||||
*Slic3r::Surface::Collection::DESTROY = sub {};
|
||||
*Slic3r::Print::SupportMaterial2::DESTROY = sub {};
|
||||
*Slic3r::TriangleMesh::DESTROY = sub {};
|
||||
*Slic3r::GUI::AppConfig::DESTROY = sub {};
|
||||
*Slic3r::GUI::PresetBundle::DESTROY = sub {};
|
||||
return undef; # this prevents a "Scalars leaked" warning
|
||||
}
|
||||
|
||||
sub _get_running_threads {
|
||||
return grep defined($_), map threads->object($_), @threads;
|
||||
}
|
||||
|
||||
sub kill_all_threads {
|
||||
# Send SIGKILL to all the running threads to let them die.
|
||||
foreach my $thread (_get_running_threads) {
|
||||
Slic3r::debugf "Thread %d killing %d...\n", threads->tid, $thread->tid;
|
||||
$thread->kill('KILL');
|
||||
}
|
||||
# unlock semaphore before we block on wait
|
||||
# otherwise we'd get a deadlock if threads were paused
|
||||
resume_all_threads();
|
||||
# in any thread we wait for our children
|
||||
foreach my $thread (_get_running_threads) {
|
||||
Slic3r::debugf " Thread %d waiting for %d...\n", threads->tid, $thread->tid;
|
||||
$thread->join; # block until threads are killed
|
||||
Slic3r::debugf " Thread %d finished waiting for %d...\n", threads->tid, $thread->tid;
|
||||
}
|
||||
@threads = ();
|
||||
}
|
||||
|
||||
sub pause_all_threads {
|
||||
return if $paused;
|
||||
$paused = 1;
|
||||
$pause_sema->down;
|
||||
$_->kill('STOP') for _get_running_threads;
|
||||
}
|
||||
|
||||
sub resume_all_threads {
|
||||
return unless $paused;
|
||||
$paused = 0;
|
||||
$pause_sema->up;
|
||||
}
|
||||
|
||||
# Open a file by converting $filename to local file system locales.
|
||||
sub open {
|
||||
my ($fh, $mode, $filename) = @_;
|
||||
|
@ -274,8 +141,4 @@ sub system_info
|
|||
return $out;
|
||||
}
|
||||
|
||||
# this package declaration prevents an ugly fatal warning to be emitted when
|
||||
# spawning a new thread
|
||||
package GLUquadricObjPtr;
|
||||
|
||||
1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue