File Coverage

blib/lib/Hook/Fork.pm
Criterion Covered Total %
statement 54 57 94.7
branch 13 14 92.8
condition 2 4 50.0
subroutine 15 16 93.7
pod 0 3 0.0
total 84 94 89.3


line stmt bran cond sub pod time code
1             package Hook::Fork;
2 6     6   3988 use strict;
  6         10  
  6         180  
3 6     6   24 use warnings;
  6         10  
  6         148  
4 6     6   6074 use parent qw/DynaLoader/;
  6         2486  
  6         24  
5              
6             our $VERSION = '0.01_01';
7              
8             __PACKAGE__->bootstrap($VERSION);
9              
10 6     6   3836 use Hook::Fork::Task;
  6         14  
  6         162  
11 6     6   18146 use Guard;
  6         4620  
  6         466  
12 6     6   40 use Scalar::Util qw(refaddr);
  6         10  
  6         866  
13              
14             my %state;
15              
16             BEGIN {
17 6     6   3434 %state = (
18             parent => {
19             head => undef,
20             tail => undef,
21             },
22             child => {
23             head => undef,
24             tail => undef,
25             },
26             before => {
27             head => undef,
28             tail => undef,
29             },
30             );
31             }
32              
33             sub make_registerer {
34 18     18 0 88 my ($which) = @_;
35 18   50     60 my $state = $state{$which} || die 'wtf';
36              
37             return sub(&) {
38 222     222   4136 my $code = shift;
39 222         566 my $obj = Hook::Fork::Task->new($code);
40              
41 222 100       486 $state->{head} = $obj if !$state->{head};
42 222 100       734 $state->{tail}->append($obj) if $state->{tail};
43 222         268 $state->{tail} = $obj;
44              
45 222 100       610 if(defined wantarray){
46             return guard {
47 204 100   204   1082 if(refaddr $obj == refaddr $state->{tail}){
48 4         10 $state->{tail} = $obj->{prev};
49             }
50 204 100       484 if(refaddr $obj == refaddr $state->{head}){
51 6         10 $state->{head} = $obj->{next};
52             }
53 204         382 $obj->remove;
54 204         1222 };
55             }
56             }
57 18         88 }
58              
59             sub make_runner {
60 18     18 0 24 my ($which) = @_;
61 18   50     48 my $state = $state{$which} || die 'wtf';
62              
63             return sub {
64 12     12   717 my $node = $state->{head};
65 12 100       2091 return if !$node;
66 9         97 do {
67 11         1001091 $node->run
68             } while ($node = $node->{next});
69 9         1024367 return;
70             }
71 18         820 }
72              
73             BEGIN {
74 6     6   24 *register_parent_fork_hook = make_registerer('parent');
75 6         24 *register_child_fork_hook = make_registerer('child');
76 6         14 *register_before_fork_hook = make_registerer('before');
77 6         20 *run_parent_hooks = make_runner('parent');
78 6         12 *run_child_hooks = make_runner('child');
79 6         20 *run_before_hooks = make_runner('before');
80             }
81              
82             sub init {
83 6     6 0 28 my $code = _init();
84 6 50       46 if( $code != 0) {
85 0           $! = $code;
86 0           die "Problem hooking fork with pthread_atfork: $!";
87             }
88             }
89              
90 18         78 use Sub::Exporter -setup => {
91 6         30 exports => [ map { "register_${_}_fork_hook" } keys %state ],
92 6     6   7934 };
  6         89566  
93              
94             sub _get_state {
95 0     0     return \%state;
96             }
97              
98             init(); # setup the main handler
99              
100             1;
101             __END__