File Coverage

blib/lib/Thread/Isolate.pm
Criterion Covered Total %
statement 22 39 56.4
branch 2 12 16.6
condition n/a
subroutine 8 9 88.8
pod n/a
total 32 60 53.3


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: Isolate.pm
3             ## Purpose: Thread::Isolate
4             ## Author: Graciliano M. P.
5             ## Modified by:
6             ## Created: 2005-01-29
7             ## RCS-ID:
8             ## Copyright: (c) 2005 Graciliano M. P.
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12            
13             package Thread::Isolate ;
14 6     6   83604 use 5.008006 ;
  6         23  
  6         276  
15            
16 6     6   33 use strict qw(vars);
  6         14  
  6         204  
17 6     6   31 no warnings ;
  6         16  
  6         235  
18            
19 6     6   35 use vars qw($VERSION @ISA) ;
  6         28  
  6         747  
20            
21             $VERSION = '0.05' ;
22            
23             @ISA = qw(Thread::Isolate::Thread) ;
24            
25             sub BEGIN {
26 6     6   35 *CORE::GLOBAL::exit = \&EXIT ;
27 6         2919 *CORE::GLOBAL::die = \&DIE ;
28             }
29            
30             #######
31             # DIE #
32             #######
33            
34             sub DIE {
35 6     6   55687 my $is_exit ;
36 6 50       43 if ( $_[0] =~ /#CORE::GLOBAL::exit#/s ) {
37 0         0 my $err = shift ;
38 0         0 $err =~ s/#CORE::GLOBAL::exit#/exit()/gsi ; ;
39 0         0 unshift (@_, $err) ;
40 0         0 $is_exit = 1 ;
41             }
42            
43 6 50       39 if ( $^S ) {
44 6         24921 my $thi = Thread::Isolate->self ;
45 0 0         $thi->add_job('SHUTDOWN') if $thi ;
46 0           CORE::die(@_) ;
47             }
48             else {
49 0 0         if ( $is_exit ) {
50 0 0         Thread::Isolate->new_from_id( $Thread::Isolate::Thread::MOTHER_THREAD )->eval(' CORE::exit() ;') if $Thread::Isolate::Thread::MOTHER_THREAD ;
51 0           CORE::exit ;
52             }
53 0           else { warn(@_) ;}
54             }
55             }
56            
57             ########
58             # EXIT #
59             ########
60            
61             sub EXIT {
62 0     0     my @call = caller ;
63 0 0         if ( $call[1] =~ /^\(eval/ ) {
64 0           my @call2 = caller(1) ;
65 0           die("#CORE::GLOBAL::exit# at $call[1] (package $call[0]) line $call[2]:\n$call2[6]\n") ;
66             }
67             else {
68 0           die("#CORE::GLOBAL::exit# at $call[1] (package $call[0]) line $call[2].\n") ;
69             }
70             }
71            
72             ###########
73             # REQUIRE #
74             ###########
75            
76 6     6   9765 use Storable () ;
  6         34500  
  6         448  
77 6     6   6615 use Thread::Isolate::Thread ;
  0         0  
  0         0  
78            
79             Thread::Isolate::Thread::start_mother_thread() ;
80            
81             ######################
82             # STORABLE SIGNATURE #
83             ######################
84            
85             use vars qw($STORABLE_SIGN $USE_EXTERNAL_PERL) ;
86            
87             BEGIN {
88             return if $STORABLE_SIGN ;
89            
90             ($USE_EXTERNAL_PERL , $STORABLE_SIGN) = ('','') ;
91            
92             if ( $STORABLE_SIGN eq '' ) {
93             if (!$USE_EXTERNAL_PERL) {
94             $STORABLE_SIGN = unpack( 'l',Storable::freeze( [] )) ;
95             }
96             else {
97             open( my $handle,
98             qq($^X -MStorable -e "print unpack('l',Storable::freeze( [] ))" | )
99             ) or die "Cannot determine Storable signature\n" ;
100             $STORABLE_SIGN = <$handle>;
101             $USE_EXTERNAL_PERL = 'Signature obtained with an external Perl!' ;
102             }
103             }
104             }
105            
106             ##########
107             # FREEZE #
108             ##########
109            
110             sub freeze {
111             if (@_) {
112             foreach (@_) {
113             if ( !defined() or ref() or m#\0# ) {
114             my ( $stable_tree , $holder ) = make_stable_tree(\@_) ;
115             my $freeze = Storable::freeze($stable_tree) ;
116             make_stable_tree($stable_tree , $holder , 1) ;
117             return $freeze ;
118             }
119             }
120             return join("\0" , @_) ;
121             }
122             else { return ;}
123             }
124            
125             ########
126             # THAW #
127             ########
128            
129             sub thaw {
130             return unless defined( $_[0] ) and defined( wantarray ) ;
131            
132             if ( (unpack('l', $_[0]) || 0) == $STORABLE_SIGN ) {
133             my $thaw = Storable::thaw( $_[0] ) ;
134             restore_stable_tree($thaw) ;
135             return wantarray ? @$thaw : $$thaw[0] ;
136             }
137             else {
138             if (wantarray) {
139             return split("\0" , $_[0]) ;
140             }
141             else {
142             return $1 if $_[0] =~ m#^([^\0]*)# ;
143             return $_[0] ;
144             }
145             }
146            
147             }
148            
149             ####################
150             # MAKE_STABLE_TREE #
151             ####################
152            
153             sub make_stable_tree {
154             my $ref = shift ;
155             my $holder = shift(@_) || [] ;
156             my $restore = shift ;
157            
158             if ( !ref $ref ) {
159             return wantarray ? ( $ref , $holder ) : $ref ;
160             }
161            
162             if (ref $ref eq 'GLOB') {
163             push(@$holder , $ref) ;
164             my $fileno = fileno($ref) || '' . *$ref ;
165             $ref = bless(['GLOB' , $fileno] , 'Thread::Isolate::FREEZE') ;
166             }
167             elsif (ref $ref eq 'CODE') {
168             push(@$holder , $ref) ;
169             $ref = bless(['CODE' , undef] , 'Thread::Isolate::FREEZE') ;
170             }
171            
172             if (ref $ref eq 'HASH') {
173             foreach my $Key ( sort keys %$ref ) {
174             &make_stable_tree($$ref{$Key} , $holder , $restore) if ref $$ref{$Key} ;
175             }
176             }
177             elsif (ref $ref eq 'ARRAY') {
178             foreach my $i ( @$ref ) {
179             $i = &make_stable_tree($i , $holder , $restore) if ref $i ;
180             }
181             }
182             elsif (ref $ref eq 'SCALAR' || ref $ref eq 'REF') {
183             $$ref = &make_stable_tree($$ref , $holder , $restore) if ref $$ref ;
184             }
185             elsif (ref $ref eq 'Thread::Isolate::FREEZE') {
186             if ( $restore == 1 ) {
187             $ref = shift @$holder ;
188             }
189             elsif ( $restore == 2 ) {
190             if ( $$ref[0] eq 'GLOB' ) {
191             if ( $$ref[1] =~ /^\d+$/ ) {
192             open(my $fh , "+<&=$$ref[1]") ;
193             $ref = $fh ;
194             }
195             elsif ( $$ref[1] =~ /^\*(.+)/s ) {
196             $ref = \*{$1} ;
197             }
198             }
199             elsif ( $$ref[0] eq 'CODE' ) {
200             $ref = eval('sub {}') ;
201             }
202             }
203             }
204             elsif (ref $ref && UNIVERSAL::isa($ref , 'UNIVERSAL')) {
205             if ( UNIVERSAL::isa($ref , 'HASH') ) {
206             foreach my $Key ( sort keys %$ref ) {
207             $$ref{$Key} = &make_stable_tree($$ref{$Key} , $holder , $restore) if ref $$ref{$Key} ;
208             }
209             }
210             elsif ( UNIVERSAL::isa($ref , 'ARRAY') ) {
211             foreach my $i ( @$ref ) {
212             $i = &make_stable_tree($i , $holder , $restore) if ref $i ;
213             }
214             }
215             elsif ( UNIVERSAL::isa($ref , 'SCALAR') || UNIVERSAL::isa($ref , 'REF') ) {
216             $$ref = &make_stable_tree($$ref , $holder , $restore) if ref $$ref ;
217             }
218             }
219            
220             return wantarray ? ( $ref , $holder ) : $ref ;
221             }
222            
223             #######################
224             # RESTORE_STABLE_TREE #
225             #######################
226            
227             sub restore_stable_tree {
228             my $stable_tree = shift ;
229             return make_stable_tree($stable_tree , undef , 2) ;
230             }
231            
232             #######
233             # END #
234             #######
235            
236             1;
237            
238            
239             __END__