Forks-Super
view release on metacpan or search on metacpan
lib/Forks/Super/LazyEval/BackgroundScalar.pm view on Meta::CPAN
$_[2] ? $_[1] cmp $_[0]->_fetch : $_[0]->_fetch cmp $_[1]
},
'-' => sub { $_[2] ? $_[1] - $_[0]->_fetch : $_[0]->_fetch - $_[1] },
'/' => sub { $_[2] ? $_[1] / $_[0]->_fetch : $_[0]->_fetch / $_[1] },
'%' => sub { $_[2] ? $_[1] % $_[0]->_fetch : $_[0]->_fetch % $_[1] },
'**' => sub { $_[2] ? $_[1] ** $_[0]->_fetch : $_[0]->_fetch ** $_[1] },
'<<' => sub { $_[2] ? $_[1] << $_[0]->_fetch : $_[0]->_fetch << $_[1] },
'>>' => sub { $_[2] ? $_[1] >> $_[0]->_fetch : $_[0]->_fetch >> $_[1] },
'x' => sub { $_[2] ? $_[1] x $_[0]->_fetch : $_[0]->_fetch x $_[1] },
# derefencing operators: should return a reference of the correct type.
'${}' => sub { $_[0]->_fetch },
'@{}' => sub { $_[0]->_fetch },
'&{}' => sub { $_[0]->_fetch },
'*{}' => sub { $_[0]->_fetch },
# A BackgroundScalar object is a HASH-type reference. Inside
# _fetch we must disable overloading of '%{}'
'%{}' => sub { $_[0]->_fetch },
'cos' => sub { cos $_[0]->_fetch },
'sin' => sub { sin $_[0]->_fetch },
'exp' => sub { exp $_[0]->_fetch },
'log' => sub { log $_[0]->_fetch },
'sqrt' => sub { sqrt $_[0]->_fetch },
'int' => sub { int $_[0]->_fetch },
'abs' => sub { abs $_[0]->_fetch },
'atan2' => sub { $_[2] ? atan2($_[1], $_[0]->_fetch)
: atan2($_[0]->_fetch, $_[1]) }
;
our $VERSION = '0.97';
# "protocols" for serializing data and the methods used
# to carry out the serialization
my %serialization_dispatch = (
YAML => {
require => sub { require YAML },
encode => sub { return YAML::Dump($_[0]) },
decode => sub { return YAML::Load($_[0]) }
},
'Data::Dumper' => {
require => sub { require Data::Dumper },
encode => sub { return Data::Dumper::Dumper($_[0]) },
decode => sub {
my ($data,$job,$VAR1) = @_;
if ($job->{untaint}) {
($data) = $data =~ /(.*)/s;
} elsif (${^TAINT}) {
carp 'Forks::Super::bg_eval/bg_qx(): ',
'Using Data::Dumper for serialization, which cannot ',
"operate on 'tainted' data. Use bg_eval {...} ",
'{untaint => 1} or bg_qx COMMAND, ',
"{untaint => 1} to retrieve the result.\n";
return;
}
my $decoded = eval "$data"; ## no critic (StringyEval)
return $decoded;
}
},
);
# a scalar reference that is evaluated in a child process.
# when the value is dereferenced, retrieve the output from
# the child, waiting for the child to finish if necessary
sub new {
my ($class, $style, $command_or_code, %other_options) = @_;
my $self = { value_set => 0, style => $style };
if ($style eq 'eval') {
my $protocol = $other_options{'protocol'};
$self->{code} = $command_or_code;
$self->{job_id} = Forks::Super::fork {
(%other_options,
child_fh => 'out',
sub => sub {
my $Result = $command_or_code->();
print STDOUT _encode($protocol, $Result);
},
_is_bg => 1,
_lazy_proto => $protocol )
};
} elsif ($style eq 'qx') {
$self->{command} = $command_or_code;
$self->{stdout} = '';
$self->{job_id} = Forks::Super::fork {
(%other_options,
child_fh => 'out',
cmd => $command_or_code,
stdout => \$self->{stdout},
_is_bg => 1)
};
}
$self->{job} = Forks::Super::Job::get($self->{job_id});
($Forks::Super::LAST_JOB, $Forks::Super::LAST_JOB_ID)
= ($self->{job}, $self->{job_id});
$self->{value} = undef;
return bless $self, $class;
}
sub _encode {
my ($protocol, $data) = @_;
if (defined $serialization_dispatch{$protocol}) {
$serialization_dispatch{$protocol}{'require'}->();
return $serialization_dispatch{$protocol}{encode}->($data);
} else {
croak 'Forks::Super::LazyEval::BackgroundScalar: ',
'YAML or Data::Dumper required to use bg_eval';
}
}
sub _decode {
my ($protocol, $data, $job) = @_;
if (defined $serialization_dispatch{$protocol}) {
$serialization_dispatch{$protocol}{require}->();
( run in 1.902 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )