#!/usr/bin/perl -sw ## ## ## ## Copyright (c) 2001, Vipul Ved Prakash. All rights reserved. ## This code is free software; you can redistribute it and/or modify ## it under the same terms as Perl itself. ## ## $Id: Forked.pm,v 1.3 2001/06/10 15:43:04 vipul Exp $ package Concurrent::Object::Forked; use Class::Loader; use overload; use Data::Dumper; use Concurrent::Debug qw(debug debuglevel); use base qw(Concurrent::Errorhandler); sub new { my ($class, %params) = @_; my $channel = $params{Channel}; my $proxy = $params{Proxy}; my $self = bless {}, $class; if (fork == 0) { # initialize our side of communication channel $channel->init(); # create the object and report status to proxy my $obj = $self->load (%params); unless ($obj) { $channel->print ( { Status => 'Failure' } ); exit 0; } else { my %status = ( Status => 'Success' ); if (my $od = $self->overloaded ($obj)) { debug ("somebody setup us the overload!"); $status{Overloaded} = 1 if $od; } $channel->print ( \%status ); } my %secondaries = ( 0 => $obj ); my $sc = 0; # call methods requested by the proxy while (my $call = $channel->getline) { my ($method, $args, $context); $obj = $$call{Secondary} ? $secondaries{$$call{Secondary}} : $secondaries{0}; $context = $$call{Context} || 'scalar'; if ($$call{Method}) { $method = $$call{Method}; debug ("calling $method() on the object"); $args = $$call{Args}; } elsif ($$call{Operation}) { my $operation = $$call{Operation}; debug ("calling overloaded method corresponding to @$operation[2] (ID: $$call{Id})"); $method = overload::Method($obj, $operation->[2]); $args = [ $operation->[0], $operation->[1] ]; } else { next } my %RV; $RV{Id} = $$call{Id}; if ($context eq 'list') { my @rv = $obj->$method (@$args); $RV{Rv} = [@rv]; } else { my $rv; if (ref $method) { # overloaded operator handler $rv = &$method ($obj, @$args); } else { $rv = $obj->$method (@$args); } if ((ref $rv) && ($rv eq $obj)) { debug ("got myself as return value"); $rv = undef; $RV{Self} = 1; } elsif ((ref $rv) && ((ref $rv) !~ /(^SCALAR|ARRAY|HASH|CODE|REF|GLOB|LVALUE$)/)) { debug ("built a secondary object"); $secondaries{++$sc} = $rv; $rv = undef; $RV{Secondary} = $sc; } debug ("$$call{Method}() returned undef.") unless $rv; $RV{Rv} = $rv; } $channel->print (\%RV); debug ("wrote result of $$call{Method} to parent...") if exists $$call{Method}; } # proxy closed the comms channel, so we close it from our side # and commit suicide undef $obj; $channel->destroy(); exit 0; } } sub load { my ($self, %params) = @_; my $loader = new Class::Loader; return $loader->_load ( Module => $params{Class}, Constructor => $params{Constructor}, Args => $params{Args} ); } sub overloaded { my ($self, $thing) = @_; return unless overload::Overloaded ($thing); return 1; } 1;